-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add GridSpec.subplots() #14421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GridSpec.subplots() #14421
Conversation
c6d05cf
to
b70de94
Compare
Looks like a good idea; it allows for a clearer and more logical flow of user code. |
2a65aa1
to
484527e
Compare
This creates the awkward situation that having a gridspec object More generally, I'm still of the opinion that gridspec is a layout submodule and hence should not carry any axes creation stuff inside. The fact that it has a One main problem I see is that I would be much more inclined to support any solution that allows
(though of course the |
Very good points, @ImportanceOfBeingErnest. Maybe |
The name If we really want to forget about the fact that gridspecs can be attached to a figure, I would rather spell this functionality |
Just to push back on this a bit. I consider this a lack in the original hierarchy of organizing elements on a figure. A figure contains a gridspec, and gridpsec "subplots" contain axes or other gridspecs. Without the top-most container, its hard to do layout at the top level. |
A gridspec is one of several ways to position axes inside a figure. Axes in a figure can be positionned according to zero or several gridspecs. Also, the same gridspec can be used to position axes in several figures. So, gridspec is not part of any hierarchy. |
I'm saying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry forgot about this one.
In my opinion, grid specs should have a parent. That convenience far outweighs the very mild convenience of being able to treat them as abstract objects that can be shared across figures. Its not exactly hard to write |
Not quite sure where this is leading us. Just from the name and original intent Disclaimer: I don't know in detail how tight_layout or constrained_layout work. I agree with @jklymak that just an abstract specification is not enough for some use-cases. To a flexible layout mechanism would be need to distribute space to a hierarchy of elements (It's a hierarchy because you have elements that consist of more basic elements; e.g. a figure may contain two Axes, each axes may have ticklabels, maybe an axes-label etc.). The relation between those elements must be specified somehow, and a good established way appear to be Layout elements that are part of the hierarchy. GUI layouts in e.g. Java and Qt work that way and I assume that our layout requirements are not too different from GUIs. That said, it would be awesome to have such a layout system. But it would need to be designed from scratch. I don't think we can morph The other way round, I see the current and proposed extensions of |
Constrained layout works for quite complex layouts just fine with the addition in 2.2 of passing a parent to the gridspec. While I guess if you were to rearchetect it from the beginning you might do it differently I’d be very surprised if you came up with something substantively different than what we have now. I personally don’t think we should let the fact that gridspec started as an abstract thing stop us from making it more concrete. The abstraction is only mildly useful whereas making it an actual container of axes is super useful. |
@timhoffm I don't see how this PR is making anything more complicated. It is essentially factoring out the |
484527e
to
740a1e9
Compare
Pushed an improved version which also supports subgridspecs; see e.g. improvements to demo_subgridspec06 (the improvement would be even clearer if the subaxes needed to be shared). |
# | ||
# `.label_outer` is a handy method to remove labels and ticks from subplots | ||
# that are not at the edge of the grid. | ||
|
||
fig, axs = plt.subplots(3, sharex=True, sharey=True, gridspec_kw={'hspace': 0}) | ||
fig = plt.figure() | ||
axs = fig.add_gridspec(3, hspace=0).subplots(sharex=True, sharey=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like chained commands like this, so maybe the first time you do it:
gs = fig.add_gridspec(3, hspace=0)
axes = gs.subplots(shares=True, sharey=True)
and then devolve to the "short cut". With the one-liner I can't help but think that subplots
is a method on fig
, whereas its really a method on the GridSpec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, either way is fine for me.
740a1e9
to
f0cf4c2
Compare
Did not have time to look into the details here, but I withdraw my original reservation that |
so that one can separately pass `gridspec_kw` directly to the gridspec constructor.
f0cf4c2
to
f8b23cb
Compare
I needed this today, and was surprised it wasn't merged! Can this get a second review? |
@ImportanceOfBeingErnest, would you like to comment on this? In discussion above and in the meeting, the consensus is moving toward merging this in a week, unless you have objections. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the concern about letting "I have a figure" leak into GridSpec
, but the benefit is also clear.
If we were doing this from scratch, we may not do it this way and it may be worth pulling an "Abstract" version of these out the top, but I don't think we should block on that.
We also briefly discussed a gs.copy_without_figure
method that returns an "un-bound" copy.
Or |
As discussed in the call, we should have "layout" objects that know about the figure and the relation of its content. That's similar to layouts in GUI (I'm thinking particularly of Qt, but that's what I'm most familiar with). I'm not 100% sure if that's exactly what I'm wondering if we are trying to make This is clearly not thought out completely, but if we consider going in such a direction, IMHO it would be a mistake to adopt the changes proposed in this PR. I'm fine if people think we should merge this anyway, but we should be aware what route we are taking here. |
Given that you mention Qt: I think Qt actually uses the same classes for bound and unbound layouts? e.g. if you have a QVBoxLayout, you typically want to attach it to a parent (well, call parent.setLayout) before you can do anything useful with it? I also doubt that you can reuse the same layout object on two parents? "The layout will automatically reparent the widgets (using QWidget::setParent())" per https://doc.qt.io/qt-5/layout.html#tips-for-using-layouts. |
That's exactly the point. QVBoxLayout is quite unlike GridSpec: It's not an abstract specification but a non-reusable container bound to actual elements. (While you can instantiate a standalone QVBoxLayout, it's only useful when bound to a parent and when you've added widgets to the layout.) I think we actually need some something like that. And I think it's better to write that from scratch than trying to modify GridSpec into it. As an abstract specification, GridSpec is a separate concept, which can coexist with bound layouts. |
What is the practical benefit of an abstract GridSpec versus a bound GridSpec? I appreciate that previously it was abstract, and then I hijacked it to be bound to make constrained_layout work. But that was really the least invasive thing I could do, versus trying to introduce a whole new bound object that did the same thing. |
Discussion at the meeting on May 4 suggests that factoring out a gridspec_layout and deprecating the unbound gridspec might be a good move. |
so that one can separately pass
gridspec_kw
directly to the gridspecconstructor.
Just the proposal at #14155; trying to get some more discussion on it by posting an actual PR :)
PR Summary
PR Checklist