-
-
Notifications
You must be signed in to change notification settings - Fork 404
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
More flexible Layout organizations #91
Comments
Well, good to see my notebooks are good for something - making mockups! ;-p When we discussed this earlier you suggested that maybe it is possible to use a |
I don't think you'll get this working very well with a GridSpace as it is. However I've always considered whether there should be another display mode for GridSpace where each row and column share axes like in Seaborn's grids. Edit: This wouldn't even be very hard to implement instead of drawing our custom axes we could just rely on the axes drawn by each subplot and selectively disable axes on all plots except the first row and last column. One wrinkle here is that RasterGridPlot cannot support this easily so we'd have to make sure that if this option is enabled then a Grid of Rasters is passed to GridPlot rather than RasterGridPlot. |
I do like the seaborn style for a GridSpace, and it would be great to support that in any case.. In general, though, I keep hoping for some general way to wrap up a set of Elements as a composite that will then be laid out just like any other. |
We've discussed this a little bit and agree that nesting Layouts in the way you suggest might be nice. Jean-Luc suggested possibly adding a
We certainly won't be implementing this for this release but I think this would be a very nice way to easily compose complex plots, especially together with the new aspect based Layouts. We could target this feature for a 1.2 release. I've also now implemented the Seaborn style grids: %%opts GridSpace [shared_yaxis=True shared_xaxis=True fig_size=150]
layout.Parameters.Sines.last By default GridSpaces will behave as they do currently, but you can enable the inner axes with the |
I love the new shared axes, and think they ought to be on by default, whenever they make sense -- I don't see who wouldn't want it to work this way. There seems to be an extra line on the right and top of the plot, though. It's great that you think that it's feasible to add nesting of Layouts in the subsequent release. I'm confused by your example, though. Isn't what you specified incompatible with Also, would this proposal add fully hierarchical support, or only one level? I.e., could one do a group of a group of a group? If that's possible in Matplotlib, supporting it would allow any arbitrary axis-aligned pattern of subplots, not just a group of a group. If you flip through any issue of Science or Nature or J. Neuroscience you can see a variety of such configurations, with HoloViews currently handling maybe 40% of the cases (a fixed or variable-sized grid with up to one item per cell). If we add support for a single additional grouping level within a grid cell, we could cover maybe 40% more. Maybe 10% would be covered by a group of groups of groups, and then the rest are just some arbitrary configuration (which if supported in HoloViews would mean allowing/requiring people to specify the locations of each item to be laid out in some canvas area, I guess, which would be independent of anything we are discussing here). Anyway, the natural way to specify nested grouping would be to use parentheses, but I don't think that's compatible with how you currently build up Layouts as flat structures. What about a method analogous to |
The attribute name (A + B + (C+D).nest(1) + E).cols(2) The idea is that (A + B + (C+D).cols(1, nest=True) + E).cols(2) Obviously you can supply (A + B + (C+D).ncols(1) + E).cols(2) You could probably use Edit 1: I should clarify that I think this is the right approach because I think you should always explicitly specify cols for an inner (i.e nested) layout. You don't want to rely on arbitrary defaults when building a complex, nested figure. Edit 2: If the ambiguity between |
Oops, you're right -- can't use I did think about proposing that cols() simply act like your proposed ncols(), since I can't think of a case where one would want .cols() not to nest in this way (is there one)? I personally think that once .cols() has been specified, the plots included should be taking up that many columns, which implies nesting if they are subsequently put into another Layout (and no change if they are not). But then I thought about the converse -- maybe someone would want to do nesting without forcing a specific number of columns? Maybe if someone has a variable number of tall thin plots in a Layout, and wants them all to fill a single large grid cell, regardless of how many of the thin plots there are? Maybe that would still be ok if it works fine to specify a large number of columns in that case, larger than one expects to use. |
I should also say I really like the new |
Good job both of you, then! I do like having the parameters on the top and right in that case; very compact and readable. |
Just one clarification, though: when I said I don't see who wouldn't want it to work this way, I was imagining figures where the axes are repeated for every single plot; this format has all the same information, with less space and busyness, so it's clearly better. But the existing GridSpace defaults are also useful, now that I directly compare them with the above -- they present a simpler view, with no inner axes at all, which is less cluttered and clearly sometimes useful. On balance, I think the shared axes version above is the best default -- provide all the information, in a usable format. But it should be easy to select the current behavior as well, with examples of how to do so in the tutorials, because the current behavior makes for clean, beautiful, and less busy plots, at the cost of not showing what the inner axes are. |
My understanding is that this will be a plot option which means we will be able to switch between the more informative and the old display - which is better when you are looking at a large number of curves to compare their shape. |
I agree a new method is preferable to a new operator, no comment on the naming yet.
The lines at the right and top indicate that it is on one axis but I could just get rid of them.
Right they are plot options, you can selectively toggle this behavior for each axis e.g. %%opts GridSpace [shared_yaxis=False shared_xaxis=True fig_size=150]
layout.Parameters.Sines.last or disable the outer axis completely: %%opts GridSpace [shared_yaxis=True shared_xaxis=True yaxis=None fig_size=150]
layout.Parameters.Sines.last
Once nesting is supported it'll be to an arbitrary level. You can already see this if you try to nest a grid within a grid, it works but the result is a mess due to overlapping labels. A grid is obviously a very tight configuration and won't ever work well with nesting (unless you make the canvas huge). Nested Layouts should be more forgiving although you'll probably have to do some fine adjustment once you go two levels deep. |
One problem with enabling the new GridSpace options by default is that at the default size you'll get overlapping labels, particularly if you put the GridSpace inside a Layout. It could be disabled automatically when it's inside a Layout, might be confusing though. |
Maybe the last numeric tick label on the right could be omitted for the x axes of all but the last plot, and the last tick label on the bottom eliminated for the y axes always (since it almost always crowds the 0.0 point on the x axis, even with font sizes that are otherwise ok)? The other options you list sound good. I'd vote for removing the top and right lines; I see what you mean about what they convey semantically, but because they overlap with the edges of the plot borders, they seem like mistakes. Maybe they would work if slightly offset above and to the right of the subplots, but that might just make the plot too busy; not sure. Regarding nesting, it's great that it will work to arbitrary levels. One issue -- when nesting Layouts, I think that people will want one of three possible behaviors for the subfigure labels:
|
Doing that would be fairly involved as the ticks would then have to be precomputed by the GridPlot or I'd have to create a custom ticker for different axes. I'm also no longer convinced it should be enabled by default, as it can far too easily get too crowded, in which case you'll have to explicitly resize it. Here's two 5x5 GridSpaces in a Layout at default sizing: It did automatically adjust the number of ticks but the x-ticks would still be massively overlapping unless I rotated them.
I just got rid of them.
Sub-sub-sub...labels would also emerge naturally out of the nesting although their positioning will probably leave a lot to be desired by default. |
Philipp's example above there suggests to me that I would like the axes on (by default) for a I believe this is possible ( Edit: Philipp already suggested this in fact. I think it is reasonable to change defaults for clarity when composing things together as long as it is possible to switch back as appropriate.
|
I agree with making the default have the most useful behavior in cases we have figured out, as long as there is a way to override it. |
Also see the discussion in #444. |
Now is probably the time to revisit this issue, because we can follow what Bokeh did to improve layouts at first, and then see whether we can just copy the same system over to matplotlib after that. I still favor being able to use + and * as always, but with some grouping mechanism that lets us combine into chunks that get laid out as single items. Adjusting the relative sizes, etc. can be then done by stretching or squashing individual plots (which are otherwise all equal), and possibly even allow adjusting the positions similarly (to allow insets, etc.). And then maybe we can copy the resulting arrangement into a template, as in PR #444, that can be applied wholesale to another layout? |
After some discussion with @philippjfr and @jlstevens today, I propose the following implementation for Layout grouping:
Open issues:
|
Sounds like a good proposal overall. Just two comments for now and one question:
At the level of the user API that is true, but I suspect the actual layout code used in plotting will need to compute across all these things. Unless we figure out a way to build plotting classes for the various
I think the rules are:
This would be flexible while making sure all the layout related classes are at the top of the hierarchy. Now for the question - although this would be far more flexible than we have now, where would layout templates fit into this? The idea of a layout template is to supply an overlay of Bounds objects (or similar) to allow precise positioning of cells in a layout. |
Could you please give an update on this issue? Many thanks for this great project! Kind regards, |
After reading this over, it appears to be the inspiration behind Panel, leading me to conclude that incorporating Panel into HoloViews will result in resolving this open issue. Is this correct? |
In the long run, yes; rebuilding HoloViews layouts on Panel would solve this problem, but it's tricky because HoloViews supports different backends, and Panel is only a good drop-in replacement for the Bokeh backend. The Matplotlib backend has its own layout system with its own important features, such as supporting SVG fully and allowing subfigure labels like in the above, and so we're not ready to replace such layouts entirely. So while moving to Panel-based layouts is a long-term goal, and we've been making good progress towards it already, it's still some ways off. Meanwhile, going in the other direction already works, and immediately allows layouts like the one at the start of this issue. You can already use HoloViews to create any groups of plots that you want to be organized together (linked and aligned), then use Panel to arrange the whole figure however you like. For interactive use and HTML, that should cover everything you need, though it's very slightly more verbose because it requires using pn.Row() and pn.Column() objects instead of the HoloViews |
HI all,
|
Are there any updates on this? I'm trying to make layouts for static publication-ready figures, but unfortunately I don't see how that's possible with holoviews at the moment. As far as I can tell, the bokeh backend does not allow easy export of layouts as vector-graphics and with the matplotlib backend all elements in the layout are restricted to the same width & height, if I'm not mistaken? This is a real bummer, since otherwise I'm a big fan of this project. |
@W-L This is indeed a long wished for feature but unfortunately nothing has changed just yet... That said, the next release of HoloViews will work with an upcoming version of panel/bokeh with greatly a reworked and improved layout engine. That might be our chance to revisit this again! |
Thanks for your answer, that sounds somewhat encouraging! Incidentally, I came across the fantastic patchworklib today. It allows for flexible compositing of matplotlib-derived plots with very simple syntax; and labeling (A, B, C, etc.) of subplots too. I'm wondering if this could be used or serve as inspiration for the matplotlib backend of holoviews? Just a thought.. |
As of e927280, Layout plots have much better support for plots of different aspect_ratios. However, there are still a variety of different organizations that people will need that are not supported. For instance, this arrangement works fine:
But I'd like to add one more plot, which doesn't currently work well. The example in C is model output, and I'd like to put the corresponding experimental data (which looks just like it), just above or below what's in C, without changing the overall size or layout of the figure. Unfortunately, it's not possible to do what this mockup shows:
I can imagine creating some dummy dimension "Model" vs. "Experiment", then putting C and D's Elements into it, and creating a GridSpace to show that dimension as the new C, but (a) I don't know if that would work, and (b) it seems like a big pain.
What I don't want to do is to end up with an overall 3x2 grid, as in this mockup (which would probably work in the latest release):
Apart from making the figure larger and more unwieldy, this approach doesn't let me line up C and D on the same timebase, nor would it work for three strips rather than 2. Stacking vertically emphasizes comparisons at each time, which is what's appropriate in this particular case. Swapping plots D and E would line up C and D, but I think they'd be very far apart from each other and there would be lots of wasted space. So I don't see how to get the appropriate organization from a Layout in this case (or in many similar cases where different plots have different sizes or aspect ratios). The new Layout code is great, since otherwise C and D would have tons of empty space in the last example, but it seems to me that we need some way of grouping several plots into a single box that works in a Layout like the other Elements and Containers do.
The text was updated successfully, but these errors were encountered: