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

tight_layout flips images when making plots without displaying them · Issue #12134 · matplotlib/matplotlib · GitHub

Repository navigation

tight_layout flips images when making plots without displaying them #12134

Closed

Description

Bug report

I am trying to make a bunch of figures on a cluster. In the process of doing so, I have discovered that images are flipped upside down when using tight_layout on GridSpec objects that do not contain the image.

However, this bug only happens when interactive mode is off. Even more strangely, it is not inverted if the figure has already been saved prior to calling tight_layout.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

x, y = np.ogrid[0:6, 0:7]
imdata = x + y

# Two column figure (with simple gridspecs for this example)
gs_left = GridSpec(1, 1, left = 0.05, right = 0.48)
gs_right = GridSpec(1, 1, left = 0.55, right = 0.98)

f = plt.figure()

# Add the image to the right column
im_ax = f.add_subplot(gs_right[0])
im_ax.imshow(imdata, extent = (0, 10, 0, 10), origin = 'upper', aspect = 'auto')

# Uncommenting the following line makes both figures correct
#f.savefig("image_ok")

# Call tight layout on the OTHER grid spec
gs_left.tight_layout(f, rect = [0.05, 0.05, 0.45, 0.95])

f.savefig("image_inverted")

Actual outcome

The image is inverted. The dark portion of the image should be on the bottom left.

Expected outcome

Matplotlib version

  • Operating system: Fedora 28
  • Matplotlib version: 2.2.3
  • Matplotlib backend: GTK3Cairo, I think maybe agg with non-interactive?
  • Python version: 3.6.6

Matplotlib was installed from Fedora's package manager.

Activity

  1. jklymak commented on Sep 16, 2018

    Member

    I don't think your code above is correct. You aren't adding gs_left.

    Regardless, I can't reproduce. I get the Actual Outcome with or without the call to tight layout, both on master and v2.2.3.

    The only way I get your "Expected" is to set origin='lower'.

  2. galenlynch commented on Sep 16, 2018

    ContributorAuthor

    Thanks for taking a look. The above code reflects when I see this behavior: I add the image to the right gridspec, and call tight_layout on the left. The output images above are from running the script above from my machine, though you are right I forgot to include the line that makes the empty axis in gs_left. When i have the chance I'll also try it on conda python.

  3. galenlynch commented on Sep 16, 2018

    ContributorAuthor

    Here is the script that I used to generate the figures above, with the call to gs_left.

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.gridspec import GridSpec
    
    plt.ioff()
    x, y = np.ogrid[0:6, 0:7]
    imdata = x + y
    
    gs_left = GridSpec(1, 1, left = 0.05, right = 0.48)
    gs_right = GridSpec(1, 1, left = 0.55, right = 0.98)
    
    f = plt.figure()
    im_ax = f.add_subplot(gs_right[0])
    other_ax = f.add_subplot(gs_left[0])
    im_ax.imshow(imdata, extent = (0, 10, 0, 10), origin = 'upper', aspect = 'auto')
    # f.savefig("image_ok")
    
    gs_left.tight_layout(f, rect = [0.05, 0.05, 0.45, 0.95])
    
    f.savefig("image_inverted")

    @jklymak I do agree that from the documentation, I should need origin='lower' but I have found that at least with interactive mode, I have to use origin = 'upper' to get my desired result.

  4. jklymak commented on Sep 16, 2018

    Member

    The above does not show the error. What backend are you using (print(matplotlib.get_backend())? I assume you are calling plt.show or running from ipython, or?

  5. ImportanceOfBeingErnest commented on Sep 16, 2018

    Member

    There is a relatively new tutorial about imshow's origin and extent available here. This shows that what is called "actual outcome" above, is indeed expected for extent = (0, 10, 0, 10), origin = 'upper'.

    So if anything is wrong, then it would the "expected outcome". And indeed using the cairo backend ("TkCairo" in my case, since I don't have GTK available), the image is inverted.

    What then happens seems that if you use tight_layout, cairo backend will for some reason fall back to agg and the expected outcome with the dark color in the upper left corner is produced, together with a warning UserWarning: tight_layout : falling back to Agg renderer.

    So in total there are two potential issues:

    • *Cairo backend mixes up origin = 'lower' and 'upper' (it just reverses their meaning it seems)
    • tight_layout will fall back to agg for some reason.
  6. ImportanceOfBeingErnest commented on Sep 16, 2018

    Member

    The "cairo flipping images" issue is been reported in #8798 and fixed in #11724. But it has not been backported to 2.2.x.

  7. galenlynch commented on Sep 16, 2018

    ContributorAuthor

    My backend is GTK3Cairo. @ImportanceOfBeingErnest is right that I get the agg warning when calling tight from python when interactive mode is off, so given the issues that he mentioned, it seems like cairo images being upside down would explain everything that I've experienced. However, I do not get the agg warning when using interactive mode, and therefore see consistently wrong behavior. To me, the "bug" is mostly that it's inconsistent... I've been pulling my hair out trying to figure out why images in my figures appear one way when plotting them without interactive mode, and are inverted when I use interactive mode. It took my a while to even narrow it down to the tight_layout call.

    I've read the tutorial a bunch of times, but it didn't seem to be accurate (didn't know about #8798) so I chalked it up to some version difference or something. I will say that the API for imshow is rather complicated once you start caring about where the image is in an axis.

    So it seems like the final verdict is that this is due to #11724 not being backported to my version of matplotlib? Should I close the issue or leave it open as a petition to backport the fix so I don't have to plot twice to get consistently oriented images?

  8. galenlynch commented on Sep 16, 2018

    ContributorAuthor

    Oh and @jklymak I was looking at the generated file. I get different behavior when I use interactive mode (which I guess is the equivalent of plt.show()?).

  9. jklymak commented on Sep 16, 2018

    Member

    This is still confusing. Running the code above as a script should not use gtk3cairo. And the bug in #8798 shouldn’t have anything to do w tight_layout. I’d also have thought that saving interactively should still have run through agg but maybe by that point the image is already incorrect. Anyhow the problem has been fixed in master. I don’t see any reason it couldn’t be back ported to 2.2.4.

  10. ImportanceOfBeingErnest commented on Sep 16, 2018

    Member

    I suppose the user's backend rcParam is simply set to gtk3cairo?!
    And then, it's a combination of both, I guess. Without the tight_layout you would probably consistently get the wrong behaviour. So appart from the flipping issue, there is also the question why tight_layout would switch the renderer and whether this is expected.
    (There is also another warning about tight_layout not being able to process the gridspecs, so I'm not even sure if it would be extected to work in this case.)

  11. galenlynch commented on Sep 16, 2018

    ContributorAuthor

    @jklymak If I just start a vanilla python shell and look at the backend, it's already gtk3cairo. Poking around, I realized that I had set it to that (and forgot about it) in my matplotlibrc file. Is there a reason to not use that backend? I did mention it as my backend in the original bug report. I just removed the matplotlibrc.

    I would definitely appreciate the bug fix being ported! If at all possible, I would like to continue to use my distro's version of matplotlib, which is currently 2.2.4. I've had pretty bad experiences trying to use conda, or other bolt-on python package mangers, on Fedora. Matplotlib installed with conda on Fedora is particularly problematic, maybe because of wayland. I invariably run into library compatibility issues resulting in segfaults, missing symbols, etc...

    @ImportanceOfBeingErnest Yes, I believe I was just getting consistently wrong behavior, which I'm ok with to be honest.

    As for the other warning, when I run into this problem when I'm making real figures, it only sometimes gives me a warning about tight_layout not being able to process the gridspecs. Often when it does give me a warning, it will still has the desired result of re-sizing subplots to make room for labels and ticks. Maybe I'm just experiencing alarm fatigue, but came to the conclusion that it was safe to ignore.

  12. ImportanceOfBeingErnest commented on Sep 16, 2018

    Member

    The probability to find some bug in the cairo backends is currently a little larger than for the agg backends. It seems the cairo backends do not get the same love as the agg backends when it comes to maintainance.
    On the other hand the agg backends currently show some really bad issues with marker and tick positionning, which are not present in the cairo case. Having both available is hence a good idea.

    As of today, the latest release of matplotlib is 2.2.3. If the bug fix was backported, it would appear in the (yet to be released) version 2.2.4. There will however be a version 3.0 released pretty soonish, which will contain this fix. The main difference is that 2.x is python2 compatible, while 3.x is python3 only. In order to get the fix you will need to use a new version anyways; whether that'll be 2.2.4 or 3.0 or the current development version from github will depend on your other requirements.

  13. galenlynch commented on Sep 17, 2018

    ContributorAuthor

    Whoops, I meant 2.2.3 -- that's the version that I'm using.

    Ok I'll keep in mind that I should try different backends when I run into issues down the road.

    Thanks again for both of your help!

  14. jklymak commented on Sep 27, 2018

    Member

    I tried to auto-backport #11724, but is says there is a conflict. If someone wants to take up the backport I don't see any problem w/ that, but I don't have the bandwidth...

  15. jklymak commented on Sep 27, 2018

    Member

    Note that 3.0 is released and should fix this bug, so I'll close..

  16. added this to the v3.0 milestone on Sep 27, 2018
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

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL