I have a medium-sized array (e.g. 1500x3000) that I want to plot at scale since it is an image. However, the vertical and horizontal scales are very different. For simplific
Running your example, everything looks good in matplotlib after zooming: no matter the resolution, results are the same and I see one pixel per axis unit. Also, trying with smaller arrays, pdfs (or other formats) work well.
This is my explanation: when you set figure dpi, you are setting the dpi of the entire figure (not only the data area). On my system, this results in the plot area occupying vertically about 20% of the entire figure. If you set 300 dpi and 10 in height, you get for vertical data axis a total of 300x10x0.2=600 pixels, that are not enough to represent 1500 points, this explains to me why output must be resampled. Note that reducing the width sometimes incidentally works because it changes the fraction of figure occupied by the data plot.
Then you have to increase the dpi and also set interpolation='none' (it shouldn't matter if resolution is perfectly set, but it matters if it is just close enough). Also you can adjust the plot position and size to take a larger part of the figure, but going back to the optimal resolution settings, ideally you want to have a number of pixel on the axis that is a multiple of your data points, otherwise some kind of interpolation must happen (think how you can plot two points on three pixels, or viceversa).
I don't know if the following is the best way to do it, there might be more suitable methods and properties in matplotlib, but I would try something like this to calculate the optimal dpi:
vsize=ax.get_position().size[1] #fraction of figure occupied by axes
axesdpi= int((Fig.get_size_inches()[1]*vsize)/R) #(or Yi*R according to what you want to do)
Then your code (reduced to the first loop), becomes:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
R, C = 1500, 3000
DATA = np.random.random((R, C))
DATA[::2, :] *= -1 # make every other line negative
Yi, Xi = 1, 10 # increment
CMP = 'seismic'
ImageFormat ='pdf'
Name = 'Image'
DataRange = (np.absolute(DATA)).max() # I want my data centred on 0
EXTENT = [0, Xi*C, 0 ,Yi*R]
NORM = matplotlib.colors.Normalize(vmin =-DataRange, vmax= DataRange, clip =True)
for i in (1,):
print i
Fig=plt.figure(figsize=(45, 10), dpi = 100*i, tight_layout=True)
Fig.suptitle(Name+str(i)+'00DPI')
ax = Fig.add_subplot(1, 1, 1)
Plot = ax.imshow(DATA, cmap=plt.get_cmap(CMP), norm = NORM, extent = EXTENT, aspect = 1, interpolation='none')
ax.set_xlabel('metres')
ax.set_ylabel('metres')
vsize=ax.get_position().size[1] #fraction of figure occupied by axes
axesdpi= int((Fig.get_size_inches()[1]*vsize)/R) #(or Yi*R according to what you want to do)
Fig.savefig(Name+str(axesdpi)+'DPI.'+ImageFormat, format = ImageFormat, dpi = axesdpi)
#plt.close()
This works reasonably for me.