excalibur1491 - 3 months ago 76

Python Question

I am having trouble with matplotlib in Python trying to create two plots side by side. I managed to make them stay next to each other, but I need them to have the exact same size: each point in the right one should be easily mapped to a location on the left one with the naked eye.

Instead, my right one (which is a scatter plot) has some margins that make it appear slightly smaller than the left (a heatmap).

The way I generate the heatmap is:

`def plot_map(matrix):`

# Plot it out

#fig, ax = plt.subplots()

fig = plt.figure()

ax = plt.subplot(1,2,1)

c = m.colors.ColorConverter().to_rgb

cm = make_colormap([(0,1,0), (1,1,0), 0.1, (1,1,0), (1,0.5,0), 0.66, (1,0.5,0),(1,0,0)])

heatmap = ax.pcolor(matrix, cmap=cm)

# Format

fig = plt.gcf()

fig.set_size_inches(20, 20)

plt.gca().set_aspect('equal')

# turn off the frame

ax.set_frame_on(False)

# put the major ticks at the middle of each cell

ax.set_yticks(np.arange(matrix.shape[0]) + 0.5, minor=False)

ax.set_xticks(np.arange(matrix.shape[1]) + 0.5, minor=False)

# want a more natural, table-like display

ax.invert_yaxis()

ax.xaxis.tick_top()

# note I could have used matrix.columns but made "labels" instead

ax.set_xticklabels(range(0,matrix.shape[0]), minor=False)

ax.set_yticklabels(range(0,matrix.shape[1]), minor=False)

ax.grid(False)

# Turn off all the ticks

ax = plt.gca()

for t in ax.xaxis.get_major_ticks():

t.tick1On = False

t.tick2On = False

for t in ax.yaxis.get_major_ticks():

t.tick1On = False

t.tick2On = False

divider = make_axes_locatable(ax)

cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(heatmap,cax=cax)

return (fig,ax)

Then the ax is passed over to another function to plot the little blue lines on the map:

`def plot_chosen(edges,endnodes,side,ax):`

for e in edges:

u = endnodes[e - 1][0]

v = endnodes[e - 1][1]

xu, yu = get_center(u,side)

xv, yv = get_center(v,side)

ax.plot([xu+0.5, xv+0.5], [yu+0.5, yv+0.5], 'k-', lw=4, color='blue',alpha=0.5)

Finally, I plot the scatter like this

`def plot_satter(edges,endnodes,side,xs,ys,data):`

plt.margins(0)

ax = plt.subplot(1, 2, 2)

# Format

fig = plt.gcf()

fig.set_size_inches(20, 20)

plt.gca().set_aspect('equal')

# turn off the frame

ax.set_frame_on(False)

# put the major ticks at the middle of each cell

ax.set_yticks(np.arange(side) + 0.5, minor=False)

ax.set_xticks(np.arange(side) + 0.5, minor=False)

# want a more natural, table-like display

ax.invert_yaxis()

ax.xaxis.tick_top()

ax.set_xmargin(0)

ax.set_ymargin(0)

# note I could have used matrix.columns but made "labels" instead

ax.set_xticklabels(range(0,side), minor=False)

ax.set_yticklabels(range(0,side), minor=False)

ax.grid(False)

# Turn off all the ticks

ax = plt.gca()

for t in ax.xaxis.get_major_ticks():

t.tick1On = False

t.tick2On = False

for t in ax.yaxis.get_major_ticks():

t.tick1On = False

t.tick2On = False

cm = make_colormap([(0,0,1), (0,1,1), 0.1, (0,1,1), (1,1,0), 0.66, (1,1,0),(1,0,0)])

resmap = plt.scatter(xs,ys, c=data,cmap=cm,edgecolors='none',alpha=0.5,s=data)

divider = make_axes_locatable(ax)

cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(resmap,cax=cax)

But I find no way of making the scatter plot as big as the heatmap. Actually, it's supposed to be as big as its colorbar, but that doesn't work either... Si this makes me think there is some margin around the scatter....

Also, is there a way I could make the whole PNG file not so square? Could it be a rectangle?

Thanks!

Answer

In order to get help, you need to provide a minimal working example. You will find out that producing such a minimal working example, **almost always** makes you find the problem and a corresponding solution yourself.

Also, structure your code!!

As we do not have the necessary knowledge of your data and the variables you are using, it is almost impossible to come up with a solution.

What you need to do is break down the problem. You are looking for the difference between two things - so make them as equal as possible. If you apply everything to both plots simultaneously, how can they be different after all?

The following code shows how you would do that and it acutally shows no difference in size of the two plots. So start from there and add the stuff you might need accordingly. One step at a time, until you find the piece of code that causes problems.

```
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable
x = np.linspace(0,100,101)
X, Y = np.meshgrid(x,x)
data = np.sin(X/2.3)*np.cos(Y/2.7)*np.cos(X*Y/20.)
fig = plt.figure(figsize=(10,5))
ax1=fig.add_subplot(121)
ax2=fig.add_subplot(122)
plt.subplots_adjust(wspace = 0.33 )
heatmap = ax1.pcolor(data, cmap="RdPu")
resmap = ax2.scatter(X,Y, c=data, cmap="YlGnBu",edgecolors='none',alpha=0.5)
for ax in [ax1,ax2]:
ax.set_frame_on(False)
ax.set_aspect('equal')
ax.invert_yaxis()
ax.xaxis.tick_top()
ax.set_xmargin(0)
ax.set_ymargin(0)
ax.grid(False)
for t in ax.xaxis.get_major_ticks():
t.tick1On = False
t.tick2On = False
for t in ax.yaxis.get_major_ticks():
t.tick1On = False
t.tick2On = False
ax.set_xlim([x[0],x[-1]])
ax.set_ylim([x[0],x[-1]])
divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("right", size="5%", pad=0.05)
plt.colorbar(heatmap,cax=cax1)
divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=0.05)
plt.colorbar(resmap,cax=cax2)
plt.show()
```

And btw, `fig = plt.figure(figsize=(10,5))`

produces a rectangle, while `fig = plt.figure(figsize=(20,20))`

produces a square.