FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Jupyter "inline" backend seems to misinterpret "figsize" with Axes3D · Issue #16463 · matplotlib/matplotlib · GitHub

Repository navigation

Jupyter "inline" backend seems to misinterpret "figsize" with Axes3D #16463

Closed

Description

I don't know if this is a bug in Jupyter/IPython or in Matplotlib ...

Bug report

Bug summary

When creating 3D plots (using Axes3D) with the "inline" backend (which is the default) in a Jupyter notebook, the argument figsize doesn't seem to work as intended. It looks like the width is ignored when calculating the figure size (but it doesn't seem to be ignored when calculating the size of the "axes" object?).

Actual outcome

First, when using fig.gca(projection='3d'), which is used in the official Matplotlib examples:

The same thing happens when using fig.add_subplot(projection='3d'):

Interestingly, a slightly different thing happens when using fig.add_axes([0, 0, 1, 1], projection='3d') and Axes3D(fig) (which is discouraged?):

Expected outcome

When using a "normal" 2D Axes, it looks as expected:

The output from fig.add_axes([0, 0, 1, 1]) is also different in this case:

Matplotlib version

  • Operating system: Debian Linux
  • Matplotlib version: master
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipykernel.pylab.backend_inline
  • Python version: 3.7.6
  • Jupyter version (if applicable): JupyterLab master

Activity

  1. jklymak commented on Feb 10, 2020

    Member

    inline use bbox_inches='tight' and hence clips the figure to the size of the drawn objects. That will lead to different sized figures if your drawn axes are different sizes.

    add_axes([0, 0, 1, 1]) says to fill the figure with the axes. bbox_inches='tight' then expands the figure to include the axes.

    I'm going to close this as its understood behaviour and not a bug per-se, though I agree the decision to use bbox_inches='tight' can cause confusion.

  2. mgeier commented on Feb 10, 2020

    ContributorAuthor

    Thanks for the quick answer @jklymak!
    I was actually already aware of the bbox_inches='tight' problem (I've even mentioned it in my pamphlet about wrong default values in the inline backend), but I didn't realize that it was also the culprit in this case!

    I'm going to close this as its understood behaviour and not a bug per-se, though I agree the decision to use bbox_inches='tight' can cause confusion.

    I was still surprised that the aspect ratio of the figure was completely changed. I would understand if some empty space were removed from all sides, but in this case a lot of "empty" space was removed from the left and right sides, but apparently not from the top and bottom?

    Are you sure that's not a bug in the bbox_inches='tight' algorithm?

    Here are a few updated screenshots. First, for comparison, two cases repeated from above:

    And now without the bbox_inches='tight' setting:

    And here's how "normal" 2D plots look without the bbox_inches='tight' setting:

  3. WeatherGod commented on Feb 10, 2020

    Member
  4. mgeier commented on Feb 14, 2020

    ContributorAuthor

    Thanks @WeatherGod, so are you saying this could be a bug?

    If yes, could you (or @jklymak) please re-open this issue?

  5. kopytjuk commented on Feb 21, 2020

    Contributor

    Hmm on my system everything works as expected:

    Windows 10
    Python 3.7.3
    matplotlib-3.1.3

    Seems to be a problem for newer releases, could reproduce it on 2bdf82b

  6. WeatherGod commented on Feb 21, 2020

    Member
  7. ImportanceOfBeingErnest commented on Feb 21, 2020

    Member

    This bisects to 64f197b which has apparently been recreated via #16472.
    So it's not visible in any released version yet.

    To make sure we're all on the same page here, let's take jupyter (lab) out of the equation and create a clear bug report here:

    import matplotlib.pyplot as plt
    from  mpl_toolkits.mplot3d import Axes3D
    
    plt.rcParams["axes.facecolor"] = "yellow"
    
    plt.subplots(dpi=72, figsize=(6,3), subplot_kw={"projection" : "3d"})
    
    plt.savefig("test1.png", facecolor="cyan")
    plt.savefig("test2.png", facecolor="cyan", bbox_inches="tight")
    plt.show()
    

    Actual outcome in 3.1.3

    direct save

    with bbox_inches="tight"

    Outcome in current master

    direct save

    with bbox_inches="tight"

    Expected outcome

    The direct save is expected. What's unexpected is the aspect ratio changing in the with bbox_inches="tight" case. The expected outcome would be something like this instead:

  8. jklymak commented on Feb 21, 2020

    Member
  9. eric-wieser commented on Feb 21, 2020

    Contributor

    What does bbox_inches="tight" do with axis("equal") in a 2d plot?

  10. 1 remaining item

  11. added
    Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
    on Feb 22, 2020
  12. added this to the v3.2.0 milestone on Feb 22, 2020
  13. anntzer commented on Feb 22, 2020

    Contributor

    Should this block 3.2? Let's say yes for safety, but feel free to untag if you think not.

  14. QuLogic commented on Feb 24, 2020

    Member

    That PR is only in master, so I don't think we need to block 3.2. That is, the outcome of @ImportanceOfBeingErnest's test on v3.2.x is the same as the 3.1.3 result.

  15. modified the milestones: v3.2.0, v3.3.0 on Feb 24, 2020
  16. talaikis commented on Mar 24, 2020

    For me, this bug is only in Linux (Ubuntu), Windows saves images ok.

  17. tacaswell commented on May 26, 2020

    Member

    ok, sorted out why this is happening.

    In

    for ax in fig.axes:
    pos = ax.get_position(original=False).frozen()
    locator_list.append(ax.get_axes_locator())
    asp_list.append(ax.get_aspect())
    def _l(a, r, pos=pos):
    return pos
    ax.set_axes_locator(_l)
    ax.set_aspect("auto")

    we freeze all of the axes postiions and set the aspect to auto for all of the axes having relied on a previous draw to have put them all in the right place. The next time we draw (for the render we actually emit) none of the axes adjust their positions / limits / etc and the transforms all progate through as we expect. Very previously Axes3D would do something about set_aspect('equal') that was sometimes right but sometimes very wrong so we disabled (to some notable protest). Previously (as of 3.2) Axes3D was always in auto mode. On master, we now treat Axes3D like it always has a fixed aspect ratio (which is not 1:1:1 but 4:4:3, see #17172). Thus on master when we set the aspect to "auto" in tight_bbox.adjust_bbox that effectively gets ignored and in the second draw we do adjust the position of the axes, the transforms all propgate and we get this issue. The pragmatic solution is to special case Axes3D and make sure that we suppress adjusting the limits is this case.

  18. added 3 commits that reference this issue on May 27, 2020
    5451b25
    390a57a
    c0ab395
  19. beasteers commented on Apr 21, 2022

    Hmm I'm still seeing this in 3.5.1 (on mac, python 3.10) - reproduced with and without jupyter

    fig = plt.figure(figsize=(20, 6))
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, wspace=0, hspace=0)
    ax = fig.add_subplot(111, projection="3d", facecolor='#000000', elev=70., azim=0, aspect='auto')
    ax.axis('off')
    ax.plot_surface(X, Y, S / 10, cmap=plt.get_cmap('magma'))

    No matter what I try I can't change the axis aspect ratio to fill the figure.

    fig.subplots_adjust(left=-1, right=2) doesn't stretch it, it just moves it back and forth

  20. tacaswell commented on Apr 21, 2022

    Member

    @beasteers I think you want https://matplotlib.org/stable/api/_as_gen/mpl_toolkits.mplot3d.axes3d.Axes3D.html#mpl_toolkits.mplot3d.axes3d.Axes3D.set_box_aspect

    Could you please post this at https://discourse.matplotlib.org (if you think it is a usage question) or open a new issue (if you think it is a bug)?

  21. diplodocuslongus commented on May 10, 2024

    I was observing exactly the same as @beasteers , Linux, python 3.10, Matplotlib 3.7.1.
    The trick to fill the figure is to use the proper combination of aspect and zoom (parameters of Axes3D.set_box_aspect), and figsize.
    An example:

    fig,ax1 = plt.subplots(1,1,figsize=(10, 6), constrained_layout=False,subplot_kw=dict(projection='3d'))
    azi = 30
    ax1.view_init(elev = 10, azim = azi)
    ax1.set_box_aspect((3,7,3),zoom = 1.5)
    fig.savefig('test.png')
    

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.topic: geometry managerLayoutEngine, Constrained layout, Tight layouttopic: mplot3d

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL