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

'bottom cannot be >= top' when using `tight_layout` · Issue #5456 · matplotlib/matplotlib · GitHub

Repository navigation

'bottom cannot be >= top' when using tight_layout #5456

Closed

Description

I'm trying to understand why sometimes I get a ValueError when using tight_layout.

The code of matplotlib is too complicated for me, but I'm trying to see what's happening using pdb.

It seems that the problem comes from what get_tight_layout_figure returns:

(Pdb) l
379                                              subplot_list=subplot_list,
380                                              ax_bbox_list=ax_bbox_list,
381                                              pad=pad, h_pad=h_pad, w_pad=w_pad,
382                                              rect=(left, bottom, right, top))
383  
384  ->     return kwargs
(Pdb) p kwargs
{'top': 0.43099934895833336, 'right': 0.97750000000000004, 'bottom': 0.56900065104166675, 'left': 0.16939941406250003}

I guess this in turns comes from what happens in auto_adjust_subplotpars, in the output of _get_bottom and _get_top:

(Pdb) p ax_bbox.ymin
0.3716666666666667
(Pdb) p tight_bbox.ymin
-0.16733398437499999
(Pdb) p ax_bbox.ymin - tight_bbox.ymin
0.53900065104166672
(Pdb) p tight_bbox.ymax
1.1673339843749999
(Pdb) p ax_bbox.ymax
0.6283333333333333
(Pdb) p tight_bbox.ymax - ax_bbox.ymax
0.53900065104166661

I don't know what ax_bbox and tight_bbox exactly are.

I just guess the algorithm to determine the figure properties do not play well with the data I want to plot. Can this be considered a bug ?

Activity

  1. jenshnielsen commented on Nov 10, 2015

    Member

    Could you provide a minimal example of what you are trying to do. That makes it easier to understand if this is a bug and how to fix it.

  2. tacaswell commented on Nov 11, 2015

    Member

    I have seen exceptions like this before if you have strings (in this case probably ylabels) on a multi-Axes figure where the text is wider than two axes.

    Without a minimal example there is not much we can do as, (as you point out) the tight layout code is rather complicated.

  3. added this to the milestone on Nov 11, 2015
  4. blaiseli commented on Nov 17, 2015

    Author

    I'm currently trying to build a minimal example, but what I can already say is that this indeed has to do with ylabels. If I shorten my label by 4 letters, the bug doesn't show up.

  5. blaiseli commented on Nov 17, 2015

    Author

    Here's an example:

    #!/usr/bin/env python
    
    import matplotlib
    matplotlib.use("PDF")
    import matplotlib.pyplot as plt
    
    import sys
    
    n = int(sys.argv[1])
    
    x = [1, 2, 3, 4, 5, 6, 7, 8]
    
    xmin = min(x)
    xmax = max(x)
    
    data1_f = [9.2579827408192e-05,
               0.0003372918804693761,
               0.0007482795416375103,
               0.0008833191108781534,
               0.0006607025669975578,
               0.00032707300226202557,
               0.00018651452667246514,
               3.514019691439356e-05]
    data1_r = [2.605700651541691e-05,
               2.89119480988452e-05,
               4.2170270917124425e-05,
               4.998876011255778e-05,
               3.1114424088781854e-05,
               1.3605595433950519e-05,
               5.257642663359189e-06,
               3.5083320041254324e-06]
    data2_f = [8.470149678300792e-05,
               0.0003150887959573901,
               0.0007836372284836411,
               0.0010760646463750388,
               0.0008765372009137937,
               0.00048812392173035456,
               0.00029758922448336404,
               5.93581217984265e-05]
    data2_r = [1.816789924161253e-05,
               2.4672634481371817e-05,
               4.221322246098976e-05,
               6.554534103019158e-05,
               4.963479723751039e-05,
               3.1058180581352124e-05,
               1.2640321929190978e-05,
               4.019617548011485e-06]
    
    # I want data1 and data2 on separate graphics, but with the same vertical scale.
    ymin = - max(max(data1_r), max(data2_r))
    ymax = max(max(data1_f), max(data2_f))
    
    y_span = ymax - ymin
    margin = y_span * 0.05
    
    plt.axis([xmin - 0.5, xmax + 0.5, ymin - margin, ymin + margin])
    axis = plt.gca()
    axis.set_autoscale_on("False")
    axis.bar(x, data1_f, facecolor="red", align="center")
    axis.bar(x, [-v for v in data1_r], facecolor="blue", align="center")
    axis.set_ylabel(" ".join(["data1"] * n))
    plt.tight_layout()
    plt.savefig("data1.pdf")
    plt.cla()
    
    plt.axis([xmin - 0.5, xmax + 0.5, ymin - margin, ymin + margin])
    axis = plt.gca()
    axis.set_autoscale_on("False")
    axis.bar(x, data2_f, facecolor="red", align="center")
    axis.bar(x, [-v for v in data2_r], facecolor="blue", align="center")
    axis.set_ylabel(" ".join(["data2"] * n))
    plt.tight_layout()
    plt.savefig("data2.pdf")
    plt.cla()

    If I call this with n = 15, the bug doesn't occur. With n = 16, it does:

    ./debug.py 15
    /usr/lib/python2.7/dist-packages/matplotlib/tight_layout.py:225: UserWarning: tight_layout : falling back to Agg renderer
      warnings.warn("tight_layout : falling back to Agg renderer")
    ./debug.py 16
    /usr/lib/python2.7/dist-packages/matplotlib/tight_layout.py:225: UserWarning: tight_layout : falling back to Agg renderer
      warnings.warn("tight_layout : falling back to Agg renderer")
    Traceback (most recent call last):
      File "./debug.py", line 72, in <module>
        plt.tight_layout()
      File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 1288, in tight_layout
        fig.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 1656, in tight_layout
        self.subplots_adjust(**kwargs)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 1516, in subplots_adjust
        self.subplotpars.update(*args, **kwargs)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 225, in update
        raise ValueError('bottom cannot be >= top')
    ValueError: bottom cannot be >= top
    
  6. modified the milestones: , on Nov 18, 2015
  7. tacaswell commented on Nov 18, 2015

    Member
    fig, ax = plt.subplots()
    ax.set_ylabel('a'*50000)
    plt.tight_layout()

    is a minimal example.

    There is a check in tight_layout that the pad can not be negative, but there also needs to be one that it can not be > .5.

  8. added 2 commits that reference this issue on Mar 15, 2016
    d5d69c7
    05d9b16
  9. josecv commented on Mar 15, 2016

    Hey guys we've written up a quick fix for this one and put in a pull request. Let us know if it's cool with you.

    Thanks!

  10. added a commit that references this issue on Mar 15, 2016
  11. 10 remaining items

  12. madanh commented on Jun 5, 2018

    Affects me on version 2.2.2

  13. jklymak commented on Jun 5, 2018

    Member

    This probably needs a better error message (its possible there already is one for 3.0, I’ve not checked, though I recall this coming up before). However, if you get this error, it means your decorators are not leaving room for your axes, and its size has shrunk to nothing. Either make your decorators smaller or your figure larger.

  14. timhoffm commented on Jun 5, 2018

    Member

    The error message is still the same on master.

  15. madanh commented on Jun 8, 2018

    @jklymak

    Either make your decorators smaller or your figure larger

    It happens when tight_layout() is called. It is resizing the elements that were OK before it was called. So it's a bug there, it must figure automatically if there's no room and leave all as is.

  16. tacaswell commented on Jun 8, 2018

    Member

    @maahn That should be what it is doing and it is notifying you it can not satisfy the constraints by raising an exception. You can then catch this and do what ever the right thing for your application is.

  17. jklymak commented on Jun 8, 2018

    Member

    Right. Or conversely, how small do you want it to make the axes before it errors?

  18. jklymak commented on Jun 10, 2018

    Member

    OK, the error here was in the logit scale as in #11386, closed by #11404

  19. vss888 commented on Jun 25, 2018

    I got the same error as a result of calling import matplotlib.pyplot as plt; plt.tight_layout(pad=1.0). The workaround, which allowed me to get rid of the error, was to reduce the font size on my legend. So, it seems, one can get the error if the legend does not fit on the figure.

    matplotlib.__version__: 2.2.2

  20. dstansby commented on May 14, 2019

    Member

    Using @tacaswell's minimum example now gives

    >>> plt.tight_layout()
    /Users/dstansby/miniconda3/lib/python3.7/site-packages/matplotlib/tight_layout.py:181: UserWarning: Tight layout not applied. The bottom and top margins cannot be made large enough to accommodate all axes decorations. 
      warnings.warn('Tight layout not applied. '

    Which I think is good enough to close this as "fixed with a sensible warning". If I've missed anything, feel free to comment or re-open this issue.

  21. EliteMasterEric commented on Aug 26, 2019

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    ax.set_ylabel('a'*50000)
    plt.tight_layout()
    

    Running the code above still results in the stack trace below, in matplotlib 3.0.3, the latest version available for Python 2.

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 1379, in tight_layout
        fig.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 1756, in tight_layout
        self.subplots_adjust(**kwargs)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 1612, in subplots_adjust
        self.subplotpars.update(*args, **kwargs)
      File "/usr/lib/python2.7/dist-packages/matplotlib/figure.py", line 230, in update
        raise ValueError('bottom cannot be >= top')
    ValueError: bottom cannot be >= top
    
  22. jklymak commented on Aug 26, 2019

    Member

    3.0.3 is not py2 compatible. Maybe you mean 2.2.3? Doubt this fix will be back ported

  23. EliteMasterEric commented on Aug 26, 2019

    Apologies, it appears the version of matplotlib I was using as 1.5.1, not 2.2.4.

    Upgrading to that version makes the above code function as expected.

  24. removed this from the future releases milestone on Oct 6, 2022
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


      Back | FazBrowse Home | New Git URL