6

I'm trying to plot a two-dimensional array in matplotlib using imshow(), and overlay it with a scatterplot on a second y axis.

oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)

plt.figure()
ax1 = plt.gca()

ax1.imshow(twoDim, cmap='Purples', interpolation='nearest')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()

#This is the line that causes problems
ax2 = ax1.twinx()

#That's not really part of the problem (it seems)
oneDimX = oneDim.shape[0]
oneDimY = 4
ax2.plot(np.arange(0,oneDimX,1),oneDim)
ax2.set_yticks(np.arange(0,oneDimY+1,1))
ax2.set_yticklabels(np.arange(0,oneDimY+1,1))

If I only run everything up to the last line, I get my array fully visualised:

That's what it is supposed to look like!

However, if I add a second y axis (ax2=ax1.twinx()) as preparation for the scatterplot, it changes to this incomplete rendering:

Incomplete visualisation of array

What's the problem? I've left a few lines in the code above describing the addition of the scatterplot, although it doesn't seem to be part of the issue.

Chris
  • 651
  • 7
  • 23
  • Reproduced on Python 2.7, matplotlib 2.1.1. This could well be a bug – DavidG Jan 15 '18 at 01:41
  • A similar system here: Python 2.7.12, Matplotlib 2.1.1. @DavidG if this turns out to be a bug, are there any workarounds to achieve this overlay with two y axes? – Chris Jan 15 '18 at 01:54
  • 2
    There is a [discussion on github](https://github.com/matplotlib/matplotlib/issues/1789/) on this issue. Apparently it has something to do with `imshow` forcing the aspect ratio of `ax1`. If you set `ax1.set_aspect('auto')` the entire image and the plot will be shown correctly, but the image will be distorted badly. – Thomas Kühn Jan 15 '18 at 07:57

1 Answers1

4

Following the GitHub discussion which Thomas Kuehn has pointed at, the issue has been fixed few days ago. In the absence of a readily available built, here's a fix using the aspect='auto' property. In order to get nice regular boxes, I adjusted the figure x/y using the array dimensions. The axis autoscale feature has been used to remove some additional white border.

oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)

plt.figure(figsize=(twoDim.shape[1]/2,twoDim.shape[0]/2))
ax1 = plt.gca()

ax1.imshow(twoDim, cmap='Purples', interpolation='nearest', aspect='auto')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()

ax2 = ax1.twinx()

#Required to remove some white border
ax1.autoscale(False)
ax2.autoscale(False)

Result:

enter image description here

Chris
  • 651
  • 7
  • 23