Skip to content

[ENH]: Specifying figure size based on width and ratio/aspect #28758

Closed as not planned

Description

@oscargus

Problem

While playing around with style files, I realize that for a paper it often makes sense to specify the width (set by the publisher) and ratio (determined by what we plot). Although one can of course read up and remember the figure width etc, it is quite convenient to just use a style file to determine the width and then set the ratio when creating the figure.

Proposed solution

There is https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.set_figheight.html so one way is of course to create the figure using the style file and then set the height suitably.

However, some options are:

set_figratio, basically:

set_figheight(self.get_figwidth()*ratio)

Add a figratio keyword to Figure (and subplots and figure and ...) that takes the width, either from figsize or add a new rcParam for figwidth. Not sure which is less confusing...

(I think one can argue that the width should be kept when modifying the ratio based on the publisher-defined argument.)

Edit: searching a bit more I found https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.figaspect which does the exact opposite to what I want. Maybe an option is to come up with a good name for a similar function that determines the size with fixed width? Although the original idea was to make it "simple".

Activity

  1. changed the title [-][ENH]: Specifying figure size based on width and ratio[/-] [+][ENH]: Specifying figure size based on width and ratio/aspect[/+] on Aug 27, 2024
  2. rcomer commented on Aug 27, 2024

    @rcomer
    Member

    Edit: searching a bit more I found https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.figaspect which does the exact opposite to what I want. Maybe an option is to come up with a good name for a similar function that determines the size with fixed width? Although the original idea was to make it "simple".

    Could we just add a parameter to figaspect so the user can choose whether the height or width is modified?

  3. oscargus commented on Aug 27, 2024

    @oscargus
    MemberAuthor

    Yeah, that would be a good way to deal with it! (Although I also hope that there can be a "simpler" way added to sort it out directly.)

  4. rcomer commented on Aug 27, 2024

    @rcomer
    Member

    Ah, I missed that figaspect only returns the height and width and doesn't do anything to a figure.

  5. timhoffm commented on Aug 27, 2024

    @timhoffm
    Member

    I believe a new standalone function would be suitable. Repurposing figaspect does not work because we'd end up with weird naming. Suggestion:

    def figsize(*, width=None, height=None, aspect=None):
        ...
    

    where exactly two of the three parameters must be given. Usage looks like

    plt.figure(figsize=figsize(width=6, aspect=2))
    

    Pro: This keeps the interfaces clean and simple
    Con: It's a bit lengthy and (like with figaspect) one has to import the function.

    I believe we can bear the cons. I'm inclied to also discourage figaspect then in favor of figsize.


    The alternative would be to pass the relevant information into the figure and do the width/height resolution there. I've not been able to come up with a good API for that (all my attempts were unreadable, clumsy or too clever: plt.figure(figsize=(width, None, aspect)) or plt.figure(figsize={"width": 2, "aspect": 2}) or plt.figure(figsize=(width, None)@aspect(2)))

  6. jklymak commented on Aug 27, 2024

    @jklymak
    Member

    @timhoffm I hope we have vanishingly few users who can't do figure(figsize=(6, 6/2)) so I don't see the advantage of figure(figsize=figsize(6, aspect=2))

    I think what @oscargus is after is the ability to se the default figsize in the style sheet, and then modify the height by an aspect_ratio kwarg so calls in the code would be figure(aspect=2).

    I think the only objection to that proposal would be that figure(figsize=(6, 6), aspect=2) would be ambiguous. But if we were clear that the height would always be modified by the ratio, I think that could work. My gut reaction in such cases, however, is to just write my own wrapper around figure/subplots that does what I want.

  7. oscargus commented on Aug 28, 2024

    @oscargus
    MemberAuthor

    I think what @oscargus is after is the ability to se the default figsize in the style sheet, and then modify the height by an aspect_ratio kwarg so calls in the code would be figure(aspect=2).

    Correct! Something like:

    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import scienceplots
    
    with mpl.style.context(["science", "ieee"]):
        fig, ax = plt.subplots(aspect=2)

    with the rationale that it is often the width which is the parameter that should be set as "fixed" by the style file.

  8. timhoffm commented on Sep 5, 2024

    @timhoffm
    Member

    I see. Can we come up with a reasonable specification that can be passed via figsize? The problem I see with aspect is that it interacts with figsize figure(figsize=(6, 6), aspect=2) is logically inconsistent; on top of being ambiguous. Can we come up with an API that explicitly states "I want the figsize with this aspect via keeping width (or adjusting height)?

  9. jklymak commented on Sep 5, 2024

    @jklymak
    Member

    So I am not good at fine-tuning in aspect space - much more comfortable just using inches. So one possibility is to let figsize=4 mean the figure is 4" high, and uses the default width. The only slight confusion there is that the usual spec is (w, h) so having one element default to the second element is a bit strange. However, I do think the "fixed width, variable height" case is common enough to warrant doing something here.

  10. timhoffm commented on Sep 7, 2024

    @timhoffm
    Member

    For only setting figure width supporting figsize=(None, 4) would be enough and more clear than figsize=4. We can easily do that - put in a PR if you like.

    But this is not the topic of the original request, which is asking for sizing to aspect.

  11. jklymak commented on Sep 7, 2024

    @jklymak
    Member

    Oh figsize=(None, 4) would be good, and could be symmetric for folks who want figsize=(6, None). @oscargus may have a strong preference for an aspect ratio here, but as I said I don't personally think in terms of aspect ratios

  12. arkapudota commented on Nov 7, 2024

    @arkapudota

    I can work on this issue!

  13. oscargus commented on Nov 8, 2024

    @oscargus
    MemberAuthor

    @oscargus may have a strong preference for an aspect ratio here, but as I said I don't personally think in terms of aspect ratios

    I think that would do. Ideally, I'd use aspect (as it is easier to guessimate that the aspect should be 2 than to try different heights when you are not really sure about the exact width), but (None, 4) is still better than not being able to modify the height without knowing (bothering to figure out) the exact width (as you really do not want to change it).

  14. timhoffm commented on Nov 11, 2024

    @timhoffm
    Member

    Ok, let's allow figsize tuples with at most one of the two entries being None. @arkapudota do you want to work on this?

    This does not restrict our ability to expand for a possible aspect definition later.

  15. arkapudota commented on Dec 2, 2024

    @arkapudota

    Yes I can work on this

  16. timhoffm commented on Mar 26, 2026

    @timhoffm
    Member

    I'll close this because it's difficult to define a reasonable API for aspects. Instead, let's focus on the simpler topic of partially setting width / height #31400.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions