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

DPI-connected bug of imshow when using multiple masked arrays · Issue #3057 · matplotlib/matplotlib · GitHub

Repository navigation

DPI-connected bug of imshow when using multiple masked arrays #3057

Description

Initial discussion started here: http://stackoverflow.com/questions/23490289/matplotlib-shows-different-figure-than-saves-from-the-show-window

Essentially I need to combine a few arrays to make a whole image I want to produce using imshow. So that the arrays do not overlay each other I use masking (as in the example at StackOverflow) or I set some data to None, so that it is not plotted; I do this:

cmap = matplotlib.cm.get_cmap()
cmap.set_bad('w', 0.0)

See the whole working example:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

data = np.random.random((3000, 3000))
data[np.tril_indices_from(data, 1)] = None
data2 = np.random.random((3000, 3000))
data2[np.triu_indices_from(data2, -1)] = None

cmap = matplotlib.cm.get_cmap()
cmap.set_bad('w', 0.0)

plt.imshow(data, interpolation='none', cmap=cmap)
plt.imshow(data2, interpolation='none', cmap=cmap)
plt.locator_params(nbins=60)
plt.show()

So the thing is, if I look at such image in an interactive window everything looks perfect (e.g. I zoomed into top-left corner, so that the pixels are visible:

If I save the whole image to a file from the Save-dialog of the window, the image gets screwed, so that the pixels are much bigger, than they should (it is a printscreen of Inkscape with opened SVG-file, where I zoomed to approximately the same coordinates):

Same goes to direct saving the image to disk (SVG):

If I use only data, but not data2, the image looks good:

If I save both of them, but change the dpi (e.g. to 900), the image changes and the so-to-say resolution gets better, but the image gets really messy:

You can probably see, that some pixels are distorted. If not, here is a closer zoom into this image:

At the same time you can see, that the white diagonal no more ends and starts in the very corner of the image.

As far as I understand, this is a bug, or at least undocumented behaviour, because I haven't found any mentioning of possibility of such weird effects anywhere. Using such plots (though not randomly generated) is crucial to my research, I would really like this fixed or being pointed out to a solution for this problem.

Please let me know, if you can reproduce such effects and if you need any further information from me.

I use matplotlib 1.3.1 on Ubuntu 14.04 with Python 2.7.6 and Spyder 2.2.5.

Activity

  1. changed the title [-]DPI-related bug of imshow when using mutiple masked arrays[/-] [+]DPI-connected bug of imshow when using mutiple masked arrays[/+] on May 10, 2014
  2. changed the title [-]DPI-connected bug of imshow when using mutiple masked arrays[/-] [+]DPI-connected bug of imshow when using multiple masked arrays[/+] on May 10, 2014
  3. tacaswell commented on May 11, 2014

    Member

    This is probably related to several other issues (see bugs connected with #3054).

    Try setting the dpi of your viewer to 72 or writing a matplotlib.use_backend('svg') before you import pyplot (which means not interactive windows), but might get around this bug.

  4. Phlya commented on May 11, 2014

    ContributorAuthor

    @tacaswell how do I set the dpi of my viewer to 72?
    matplotlib.use('svg') and saving to .svg doesn't help.

  5. tacaswell commented on May 11, 2014

    Member

    You have to make sure you use use (sorry for getting the call wrong) before you import pyplot. iirc something like fig.set_dpi(72).

  6. Phlya commented on May 13, 2014

    ContributorAuthor

    No problem. Yeah, I call use before importing pyplot, I know about that.
    Unfortunately setting dpi to 72 does not really help, though visible dpi of the image increases! If I make it even lower (e.g. 36) it gets even better. But still, there are artifacts in the image with distorted pixels etc., and I am not sure if there are all the pixels there that should be.

  7. added this to the v1.4.0 milestone on May 17, 2014
  8. tacaswell commented on Jun 2, 2014

    Member

    I don't really understand what is going on here, but

    • you can reproduce this with the Agg backends
    • if you use smaller num- ber of pixels the edges get 'wavy'
      • if you change interpolation='none' -> 'intertolation='nearest'` this works correctly on master.
    • but it still does not work with 3k
    • if you use a smaller number of pixels you can see a pattern of narrow and wide pixels (ex 5 narrow, 1 wide)
      • the pitch of the wide pixel changes if you change the figure size
    • pushing the dpi up even more makes things better

    I suspect that there is beating going on between the pixelated data and the rasterization. Some times adjacent pixels in the saved image fall in the same pixel of the input data, but most of the time each saved pixel gets it's own data pixel (see https://en.wikipedia.org/wiki/Moiré_pattern).

    I am not sure I understand the diagonal issue, but I think the above explains the non-square pattern. I am inclined to close this as not a bug. Things are behaving correctly and the best they can under the given input parameters.

  9. Phlya commented on Jun 2, 2014

    ContributorAuthor

    @tacaswell Yeah, thank you for such a thorough explanation. I agree it might be happening because of such effects and that even it might not be a bug (though I don't really think so - plotting image of the same resolution with the same dpi, but from a single matrix doesn't cause such weird things), but in that case I would really like to know how to plot such data with imshow in matplotlib. Maybe there is a way to calculate the required dpi or smth else.

  10. efiring commented on Jun 3, 2014

    Member

    @phyla, is the intention to have an svg file with 9,000,000 pixels in it? With no loss of information, so that when you zoom in, you see each pixel? It will be a big file. When not zoomed in, it will be up to the renderer to decide how to handle its inability to show all the pixels.
    It seems like there should be a simple way to achieve this, and it makes sense that interpolation='none' should do the trick--or protest if owing to some limitation, it can't. Evidently, however, this is not the case. A pull request was recently merged, illustrating how 'none' and 'nearest' differ: #2995.
    It seems that in order to store an image with a 1:1 correspondence between pixels and the original image array, a calculation of exactly the right dpi for the savefig command is needed. This can only work, however, if the figure has no more than one image, since a single dpi must fit all.
    I think we should be able to get around this for svg and pdf.

  11. Phlya commented on Jun 3, 2014

    ContributorAuthor

    @efiring Yes, that is the intention. And it works fine with single image without any fancy dpi calculations, and the file is not too big after that.

  12. efiring commented on Jun 3, 2014

    Member

    Aha! Superimposing images triggers a compositing operation in the draw method, which is defeating the 'none' interpolation by doing its own calculation of the grid. It is not immediately clear to me whether this can be fixed reasonably easily; if so, it would presumably be only in the special case like yours where the images are identical in grid and extents.
    I think the immediate solution for your case would be for you to do the compositing yourself in a numpy array, so that you are only calling imshow once in a given axes.

  13. Phlya commented on Jun 3, 2014

    ContributorAuthor

    What do you mean by compositing in a numpy array? To combine images in a single array? The thing is they might need a different scale of a colormap, so that they are both drawn with the same colour interval, and I would prefer not to change their values, so that it is possible to see the original signal intensity...

  14. efiring commented on Jun 3, 2014

    Member

    Yes, combine in a single array. If they need to be scaled differently, then use a suitable scaling transformation for each chunk before combining them. You could use a Normalize instance to do this, one instance per chunk, so it would be the same operation as occurs when you call imshow twice. You can get exactly the same result, very easily and efficiently. Check out the colors.Normalize class.

  15. Phlya commented on Jun 3, 2014

    ContributorAuthor

    Thank you for the idea with Normalize, I didn't know about that nice function, should be useful! I will try it out.

  16. 10 remaining items

  17. removed this from the milestone on Jul 17, 2015
  18. tacaswell commented on Jul 17, 2015

    Member

    Punted as we still have not sorted out what is going on and probably won't get to it in the next week.

    However there are now at least 3 issues that I suspect are related #1441 and #4584

  19. mdboom commented on Dec 30, 2015

    Member

    Sorry to come so late to the discussion -- you can set the rcParam image.composite_image to False to turn off the compositing of images.

  20. added 4 commits that reference this issue on Dec 30, 2015
    e904b90
    9416905
    724a9bb
    e0201d3
  21. added 3 commits that reference this issue on Jan 25, 2016
    c8d02a4
    5e14905
    fe3a171
  22. added a commit that references this issue on Feb 9, 2016
    af067d9
  23. added a commit that references this issue on Feb 17, 2016
    6e60ebf
  24. modified the milestones: , on Feb 18, 2016
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

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL