pythonmatplotlibplotscalingdistortion

Matplotlib: uneven grid size when plotting diagonal matrix


I have noticed a frustrating problem with Pythons Matplotlib where matrix plotting produces an uneven grid. This issue is persistent with and without high DPI, as well as in EPS files.

The following code is used for the image generation:

import matplotlib.pyplot as plt
import numpy as np

arr = np.zeros((200,200))
# Set the diagonal to 1
arr[np.arange(200), np.arange(200)] = 1

plt.matshow(arr)
plt.savefig('matshow_test.png', dpi=1000)

DPI=1000: Text

Which has the sizes 65x65, 90x90, 95x95, 90x90, 95x95 and so on.

DPI=default Text

Which varies between 1x1 and 2x2 for each cell.

EPS rendered in latex: Text

Which is clearly distorted.

My questions are:

  1. Why is this the default behaviour of Matplotlib?
  2. How can I fix this?

Using Python 3.9.10 with Matplotlib 3.5.1


Solution

  • The matplotlib function matshow uses an antialiasing filter on the images. Unfortunately it is enabled even for vector graphic backends such as (e)ps, pdf or svg. That means, the image is rasterized, antialiased to a specific size and than inlined in the vector graphic.

    Antialiasing takes into account a specific display resolution (dpi) and image size. If you change those parameters when viewing an image (for example when zooming in) the image can get heavily distorted, as you have experienced.

    There is a discussion about the default antialiasing for matplotlib imshow (and also matshow which uses the same mechanism) here.

    You should be able to fix your issue (and get true vector graphics) by disabling the antialiasing with the

    matshow(..., interpolation='none')
    

    option.