Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Adding subfigure_mosaic#26061
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Adding subfigure_mosaic#26061
Conversation
I have a question about **kwargs. Am I correct in thinking that we should be using that in |
I think what you have done makes sense. |
@rcomer Thank you for answering! defsubfigure_mosaic(self,mosaic,**kwargs):ret=self._sub_prep(mosaic,self.add_subfigure,kwargs) instead of what is currently happening. But the definition of |
lib/matplotlib/figure.py Outdated
} | ||
per_subplot_kw = self._norm_per_subplot_kw(per_subplot_kw) | ||
per_subthing_kw = self._norm_per_subplot_kw(per_subthing_kw) |
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.
Does this normalization also need to be changed?
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.
Do you mean changing the name to_norm_per_subthing_kw
or changing the internal implementation? I checked and it seems to be working both foradd_subplot_mosaic
andadd_subfigure_mosaic
.
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.
ah, just went and checked the source, this is a class method that is making sure that the multiple ways to reference a sub-object do not end up trying to address a given element more than once.
The classmethod needs a better name (I named it and the current name is....bad), maybe_check_for_subthing_kw_conflicts
?
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.
My first thought was_flatten_subthing_kw
but your version sounds more descriptive of what the method's actually being used for. Should I go ahead and change it to that?
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.
flatten
is also pretty good (maybe better). In general, the prior should be "Tom is bad at naming things".
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.
Is something like_check_duplication_and_flatten_subthing_kw
too long?
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.
it is an internal method, so no ;)
turnipseasonJun 8, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
Got you :) I'll change it to that if you're ok with it, then.
Edit: this was two symbols too long for flake8, so I renamed it to_check_duplication_and_flatten_kwargs
The reason we do not use Currently |
It looks like the mosaic tests all passed so that is a good sign! |
Uh oh!
There was an error while loading.Please reload this page.
Code is looking good, now it needs docs, examples and whats new :) @turnipseason What are the odds of you having time to get this done in the next two weeks? We are getting ready for the 3.8 release and it would be great to get this in for that! |
@tacaswell I've been a bit busy the past week but now I think I will have the time to do this! |
turnipseason commentedJun 26, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@tacaswell Hi! I've been trying to write small examples and discovered some problems.
inner= [ ["inner A"], ["inner B"], ]outer_nested_mosaic= [["main",inner], ["bottom","bottom"],]axda=plt.figure(layout="constrained").subfigure_mosaic(outer_nested_mosaic) This (with some keywords for clarity + identify_axes) gives us: Is this expected? Should I try to fix this behavior or just write into the docs that it shouldn't be used like that?
|
Please try to fix thisor make it error in this case
|
This look related to this PR. |
This is a helper function to build complex GridSpec layouts visually. | ||
See :doc:`/gallery/subplots_axes_and_figures/subfig_mosaic` |
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.
This does not appear to have been added?
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.
Yes, I haven't added the example yet. Working on it, though!
lib/matplotlib/figure.py Outdated
# separate SubFigures for nested layouts, | ||
# otherwise they will all create without nesting. | ||
subfigs_for_nested = {} | ||
if sub_add_func.__name__ == 'add_subfigure': |
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.
Checking the name of a passed in method is generally a bad sign!
To understand the problem here it is that when there are nested sub figures we need to switch which (sub) figuresadd_subfigure
we pass down through?
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.
Essentially, yes. I wanted to keep track of all of the nested figures (in any 'level' of nesting) with thesubfigs_for_nested
dictionary, so that later on I could assign the correct nested figures their parent 'dummy' figure (and they got positioned correctly). Sincesubplot_mosaic
worked just fine with nesting already, I did this.
lib/matplotlib/figure.py Outdated
@@ -2084,7 +2062,9 @@ def _do_layout(gs, mosaic, unique_ids, nested): | |||
nested_output = _do_layout( | |||
gs[j, k].subgridspec(rows, cols), | |||
nested_mosaic, | |||
*_identify_keys_and_nested(nested_mosaic) | |||
*_identify_keys_and_nested(nested_mosaic), | |||
sub_add_func, |
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.
If you did this as
subadd_func if subfigs_for_nested.get(key) is None else subfigs_for_nested[key].add_subfigure:
then you would still only need to pass one piece of information into the recursive call
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.
Ok, I think I see what you mean. I changed it to what you suggested, plus the internal code for the_get_subfigs_from_nested
and it seems to work. I'll test it a bit more and amend the PR if it looks good. Thank you!
A visual layout of how you want your Axes to be arranged | ||
labeled as strings. For example :: | ||
sub_add_func : `.Figure.add_subplot` for `.Figure.subplot_mosaic` and |
tacaswellJul 20, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
ok, so I think the fix to this nested figure problem is to change the signaturesub_add_func
. The input should stay the same, but the return should be the returned thingand the nextsub_add_func
to use.
For axes it would be
def_add_func(*args,**kwargs):returnself.add_subplot(*args,**kwargs),_add_funcreturnself._sub_prec(mosaic,_add_func, ...)
and for subfigures it would be a bit fancier like
def_factory(fig):def_add_sub_func(*arg,**kwargs):new_fig=fig.add_subfigure(*args,**kwargs)returnnew_fig,_factory(new_fig)returnself._sub_prec(mosaic,_factory(self), ...)
and then where you call it it would be
new_thing, sub_add_func = sub_add_func(....)
That way we do not have to special case anything in the_sub_prep
code or have the awkward sometimes we use one input sometimes we use the other behavior on the internal API.
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 also have not tried this code so it is probably only 90% correct, but I am pretty confident it is pointing in the right direction.
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.
Just to not leave this unanswered after my previous comments elsewhere - this will definitely require some thought. Sorry I can't do it right away, but I'll get on it in the morning and, hopefully, make it work :)
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.
"recursion" is called that because you curse it again and again.....
sf.set_linewidth(2.1) | ||
identify_subfigs(subfigs) | ||
# %% |
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.
The subplot_mosaicexample also has a version of this using gridspec_kw. But for subfigures the following analogous code:
mosaic="""AA BC"""fig=plt.figure()subfigs=fig.subfigure_mosaic(mosaic,subfigure_kw={'edgecolor':'black','linewidth':2},gridspec_kw={"bottom":0.25,"top":0.95,"left":0.1,"right":0.5,"wspace":0.5,"hspace":0.5, },)identify_subfigs(subfigs)subfigs=fig.subfigure_mosaic(mosaic,subfigure_kw={'edgecolor':'black','linewidth':2},gridspec_kw={"bottom":0.05,"top":0.75,"left":0.5,"right":1,"wspace":0.5,"hspace":0.5, },)identify_subfigs(subfigs)
gives this:
when it should look like this:
So the only gridspec_kws that are actually being taken into account (if specified) are width/height ratios.
1e3b3e7
to7c450a2
CompareI took the liberty of rebasing this again + a few little fix ups at it seems to work. |
…e method subfigure_mosaic, added a method for both of them to use.
fb45567
to9f8563e
CompareI thought I was going to need |
Uh oh!
There was an error while loading.Please reload this page.
PR summary
Resolves#25949
Made initial changes:
subplot_mosaic
_sub_prep
method that contains thesubplot_mosaic
logicsubfigure_mosaic
Still needs to be done:
PR checklist