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

Incorrect imshow extent in PDF backend · Issue #8981 · matplotlib/matplotlib · GitHub

Repository navigation

Incorrect imshow extent in PDF backend #8981

Description

Bug report

Bug summary

When plotting with imshow using the PDF (or SVG) backend the right and top edges of the extent are not correct. The left and bottom edges seem to be correct.

The deviation is small but noticeable (I used a smaller figure size to make it more visible -- it seems not to scale with figure size). It also appears to be unaffected by the interpolation mode. I noticed while returning to an old set of scripts -- I think this wasn't an issue for MPL pre-2.0 but unfortunately I'm unable to be more specific than that.

A minimal code example is given below (I've tested it with a blank matplotlibrc as well and the issue persists).

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
fig.set_size_inches([2,2])
ax = fig.add_subplot(111)

x0, x1 = 0.0, 1.0

ax.set_xlim(x0-0.1,x1+0.1)
ax.set_ylim(x0-0.1,x1+0.1)

ax.plot([x0,x0],[x0,x1],color='r',lw=0.1)
ax.plot([x1,x1],[x0,x1],color='r',lw=0.1)
ax.plot([x0,x1],[x0,x0],color='r',lw=0.1)
ax.plot([x0,x1],[x1,x1],color='r',lw=0.1)

ax.imshow(np.zeros((16,16))+0.5,
          cmap='Blues',
          origin='lower left',
          extent=(x0,x1,x0,x1),
          interpolation='none',
          vmin=0,vmax=1)

fig.savefig("minimal.pdf")
fig.savefig("minimal.png",dpi=600)

Actual outcome

The red outlines (set to match the extent) are not at the edge of the blue square. See the PDF examplee and the zoomed version (attached below).

minimal.pdf

Expected outcome

The red outlines (set to match the extent) should be at the edge of the blue square. See the PNG example and the zoomed version (attached below).


Matplotlib version

  • Operating System: Linux 4.12.3-1-ARCH
  • Matplotlib Version: 2.0.2 (Both packaged from Arch and latest version compiled myself)
  • Python Version: 2.7.13 and 3.6.2

Activity

  1. WeatherGod commented on Aug 2, 2017

    Member
  2. self-assigned this
    on Aug 2, 2017
  3. jkseppan commented on Aug 2, 2017

    Member

    Looks like a bug to me.

  4. radioactivist commented on Aug 2, 2017

    Author

    @WeatherGod The issue appears for me in evince and in the Chromium and Firefox PDF viewers. It also appears when rasterizing the PDF in gimp (as I did to generate the zoomed version).

  5. added this to the milestone on Aug 2, 2017
  6. tacaswell commented on Aug 2, 2017

    Member

    @jkseppan before you dig too fare into the imshow code have a look at #8966 . I suspect that won't affect this, but is a big change that maybe on the code path.

  7. QuLogic commented on Aug 2, 2017

    Member

    A workaround is to set the imshow to be rasterized (even though that seems redundant) and then set a higher dpi (which is only used for rasterization on vector backends like PDF):

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    fig.set_size_inches([2, 2])
    ax = fig.add_subplot(111)
    
    x0, x1 = 0.0, 1.0
    
    ax.set_xlim(x0-0.1, x1+0.1)
    ax.set_ylim(x0-0.1, x1+0.1)
    
    ax.plot([x0, x0], [x0, x1], color='r', lw=0.1)
    ax.plot([x1, x1], [x0, x1], color='r', lw=0.1)
    ax.plot([x0, x1], [x0, x0], color='r', lw=0.1)
    ax.plot([x0, x1], [x1, x1], color='r', lw=0.1)
    
    ax.imshow(np.zeros((16, 16))+0.5,
              cmap='Blues',
              origin='lower left',
              extent=(x0, x1, x0, x1),
              interpolation='none',
              vmin=0, vmax=1, rasterized=True)
    
    fig.savefig("minimal.pdf", dpi=300)
    fig.savefig("minimal.png", dpi=600)

  8. radioactivist commented on Aug 5, 2017

    Author

    I've done a little digging into the source code to try and nail down what's causing this. By looking at the raw SVG output I was able to trace it to something in the transform being passed into the backend. This line in the _make_image function in the file image.py appears to be the issue; if I comment this line out then the error disappears in both the PDF and SVG output. Interestingly the PNG output also still looks correct (this is for the v2.0.2 code).

    I have no real idea what this line is intended to fix, so I don't know what the appropriate change is. (I came to it since the references to sub pixels and such seemed odd for vector output).

  9. tacaswell commented on Aug 5, 2017

    Member

    attn @QuLogic I think you were looking at this sort of thing during the 2.0 release?

  10. QuLogic commented on Aug 5, 2017

    Member

    Well, the last change was mine, to remove a +1 to the new width/height rounding. Now it is likely very close to matching in PNG output, but you can't say it will work without the adjustment before checking various sizes to try and trigger the round up.

    I guess it makes sense that this is a problem with PDF and SVG since they use a relatively low dpi (because it's really points-per-inch, not pixels/dots). I'm not sure how _make_image is called, but if we can get round_to_pixel_border to be false when using the PDF/SVG backends, that might be enough.

  11. modified the milestones: , on Aug 5, 2017
  12. modified the milestones: , on Oct 9, 2017
  13. laborleben commented on Nov 23, 2018

    This bug (or regression because this wasn't an issue in matplotlib 1.5.x) is still not fixed in matplotlib 2.2.3.

    The misalignment is quite significant and it is an annoying bug. I get the misalignment with all output formats: pdf, png, svg, etc.
    The misalignment seems to increase from bottom to top.

    Expected result (1.5.x):

    Actual result (2.2.3):

    Code to reproduce the bug

    import matplotlib.pyplot as plt
    import matplotlib.patches
    import numpy as np
    arr = np.zeros((5000, 5000), dtype=np.uint8)
    arr[4000:4010, :] = 200
    arr[2990:3000, :] = 200
    arr[:, 4000:4010] = 200
    arr[:, 2990:3000] = 200
    arr[3990:4000, 3990:4000] = 100
    arr[3000:3010, 3990:4000] = 100
    arr[3990:4000, 3000:3010] = 100
    arr[3000:3010, 3000:3010] = 100
    extent = [0.0, 5000.0, 0.0, 5000.0]
    plt.imshow(arr, aspect="auto", origin="lower", interpolation='none', extent=extent)
    rect = matplotlib.patches.Rectangle(xy=(3000.0, 3000.0), width=1000.0, height=1000.0, linewidth=0.5, facecolor='none', edgecolor='m')
    ax = plt.gca()
    ax.add_patch(rect)
    plt.xlim(2900, 4100)
    plt.ylim(2900, 4100)
    plt.savefig("test_extent_1_1.pdf")
  14. github-actions commented on Apr 16, 2023

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  15. jklymak commented on Apr 16, 2023

    Member

    I think #17182 will fix this.

  16. added
    keepItems to be ignored by the “Stale” Github Action
    and removed
    status: inactiveMarked by the “Stale” Github Action
    on Apr 16, 2023
  17. jklymak commented on Apr 17, 2023

    Member

    #17182 doesn't fix this. The problem is the same as #17182 though.

    interploation != 'none'

    For the rasterized imshow, suppose the pdf dpi is 20 dpi, but the width of the image as specified by the axes size and "extent" must be 1.571", then the image would need to be 31.42 pixels wide to fit precisely. So we round up to 32 pixels, but then the image overflows its extent. For this case, what should happen is the image size gets rounded up (ceil(1.57*20)=32 pixels), and then the image dpi would be increased accordingly in the PDF to 32/1.571 = 20.3692 dpi.

    Of course the problem is not usually as bad as this. For 200 dpi the image would need to be 314.2 pixels wide, and the adjusted dpi would be 200.51.

    interpolation == 'none'

    See #25704 for what I think is a solution....

  18. removed
    keepItems to be ignored by the “Stale” Github Action
    on Apr 25, 2023
  19. modified the milestones: v3.8.0, v3.7.2 on Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


    Back | FazBrowse Home | New Git URL