Missing Segments in Output of imshow()

Hi,

I am experiencing missing “segments” in the output of imshow(). I draw a slowly growing line in an array, and then display it. The line is continuous but in the output, there are segments missing from it. Of course, if I zoom into the picture (before saving to output), then I can see the lines. However, if I save directly to a file then the segments are missing.

Here is a minimal example:

“”"

import numpy as np

import matplotlib.pyplot as plt

N = 600

slope = 15

x = np.zeros((N,N))

j = np.arange(N)

i = N/2 - j/slope

for idx in zip(i,j):

x[idx] = 1

plt.imshow(x, interpolation=‘nearest’, cmap=plt.cm.gray_r)

plt.savefig(‘bug.pdf’)

plt.savefig(‘bug.png’)

“”"

I have attached an example of the output. In theory, there should be a continuous line from the left side of the picture to the right side. The problem seems to occur across backends. Additionally, the thickness of the segments is not uniform. Some are thinner than the rest. Decreasing the value of N seems to make the issue go away. Increasing the value of N makes the problem worse.

Any ideas on what is going on and how I can fix it?

bug.pdf (32.4 KB)

I am experiencing missing "segments" in the output of imshow()....

Here is a minimal example:

I have attached an example of the output. In theory, there should be a continuous line from the left side of the picture to the right side. The problem seems to occur across backends. Additionally, the thickness of the segments is not uniform. Some are thinner than the rest. Decreasing the value of N seems to make the issue go away. Increasing the value of N makes the problem worse.

Any ideas on what is going on and how I can fix it?

Imshow scales your geometry according to the figure size, and if you *insist* on having the "nearest" interpolation, you may lose pixels while drawing, it is as simple as that. No miracles.

How to fix it?
1. Use bilinear, or sinc, or any smooth interpolation.
2. Make your figure big enough, say plt.figure(figsize=(14,14)).

Jerzy Karczmarczuk

Agreed.

Your example above is basically the equivalent of rasterizing a line (without anti-aliasing) and then down-scaling and possibly causing some stretching due to changes in aspect ratio.

Because imshow() is unaware the you are actually drawing a line, the backends can not take advantage of their “bag-o-tricks” to make it look good.

Perhaps the example you provided was an oversimplified version of the problem you are having?

Cheers!
Ben Root

···

On Wednesday, February 8, 2012, Jerzy Karczmarczuk <jerzy.karczmarczuk@…3937…> wrote:

I am experiencing missing “segments” in the output of imshow()…

Here is a minimal example:

I have attached an example of the output. In theory, there should be
a continuous line from the left side of the picture to the right side.

The problem seems to occur across backends. Additionally, the
thickness of the segments is not uniform. Some are thinner than the
rest. Decreasing the value of N seems to make the issue go away.

Increasing the value of N makes the problem worse.

Any ideas on what is going on and how I can fix it?

Imshow scales your geometry according to the figure size, and if you

insist on having the “nearest” interpolation, you may lose pixels
while drawing, it is as simple as that. No miracles.

How to fix it?

  1. Use bilinear, or sinc, or any smooth interpolation.
  1. Make your figure big enough, say plt.figure(figsize=(14,14)).

Jerzy Karczmarczuk

Jerzy Karczmarczuk wrote the following on 02/08/2012 05:55 PM:

I am experiencing missing "segments" in the output of imshow()....

Here is a minimal example:

I have attached an example of the output. In theory, there should be
a continuous line from the left side of the picture to the right side.
  The problem seems to occur across backends. Additionally, the
thickness of the segments is not uniform. Some are thinner than the
rest. Decreasing the value of N seems to make the issue go away.
  Increasing the value of N makes the problem worse.

Any ideas on what is going on and how I can fix it?

Imshow scales your geometry according to the figure size, and if you
*insist* on having the "nearest" interpolation, you may lose pixels
while drawing, it is as simple as that. No miracles.

How to fix it?
1. Use bilinear, or sinc, or any smooth interpolation.
2. Make your figure big enough, say plt.figure(figsize=(14,14)).

Taking the image size to (30,30) made all the segments appear, but their thickness was still not uniform. Using some sort of smoothing helped, but it still not displaying what the matrix was specified as: a set of blocks, somewhat resembling a line, all of which are the same color and thickness.

Can I have matplotlib show the matrix as I have specified it? Or is that too naive (on my part)?

Christopher Ellison :

Taking the image size to (30,30) made all the segments appear, but their
thickness was still not uniform. Using some sort of smoothing helped,
but it still not displaying what the matrix was specified as: a set of
blocks, somewhat resembling a line, all of which are the same color and
thickness.

Can I have matplotlib show the matrix as I have specified it? Or is
that too naive (on my part)?

Thickness is not uniform, since the system MUST truncate something when you code your drawing as you do.
With sinc or bilinear interpolation you will see non-uniform shades of gray.
Bicubic interpolation will be - probably - much better.

But if you want to see your matrix as you want to see it, don't use imshow. Use figimage.

plt.figure(figsize=(7.5,7.5))
plt.figimage(x,cmap=plt.cm.gray_r)

And, for goodness sake... Don't shoot yourself in the foot by savefig, which stores not the matrix, but the figure, the drawing
of it after all the calamities. Use

plt.imsave('bug.png',x,cmap=plt.cm.gray_r)

Good luck.

Jerzy Karczmarczuk