I'm trying to plot two images on the same axes. Here is the code I'm experimenting with (I'm new to MatplotLib - so apologies in advance)...
import matplotlib.pyplot as plt
from matplotlib import transforms
img = plt.imread('image1.gif')
fig = plt.figure()
ax = fig.add_subplot(111)
rotation_in_degrees = 60
tr = transforms.Affine2D().rotate_deg(rotation_in_degrees)
ax.imshow(img)
ax.imshow(img, transform=tr)
plt.show()
There are two issues. Firstly, only the first image appears in the display; the second is only partially shown. Is there a way to show the two images in the same plot? That is, the axes are automatically scaled.
Secondly, as you can see, I'm trying to rotate the image but I'm sure that I'm not doing correctly in the sense I don't know if I'm rotating it around the origin of the plot etc. Any advice or links for other posts would be great!
Thanks for you help in advance.
To solve your firs problem - you need to display each image in separate subplot, now - you are plotting in the same subplot. See example of plotting in separate plots:
import matplotlib.pyplot as plt
from matplotlib import transforms
img = plt.imread('image.gif')
fig = plt.figure()
rotation_in_degrees = 60
tr = transforms.Affine2D().rotate_deg(rotation_in_degrees)
ax = fig.add_subplot(121)
ax.imshow(img)
ax = fig.add_subplot(122)
ax.imshow(img)
plt.show()
For the second issue with rotation - I would use PIL:
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open('image.gif')
fig = plt.figure()
rotation_in_degrees = 60
ax = fig.add_subplot(121)
ax.imshow(img)
img2 = img.rotate(rotation_in_degrees)
ax = fig.add_subplot(122)
ax.imshow(img2)
plt.show()
Related
I would like to plot multiple PSD obtained with plot_psd() from MNE python.
I tried the following code
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3,1)
plt.figure()
ax = plt.axes()
# First plot
ax1 = fig.add_subplot(gs[0]
raw_egi.plot_psd(ax=ax1)
ax2=fig.add_subplot(gs[1]
raw_ws_ds_hp_lp.plot_psd(ax=ax2)
ax3= fig.add_subplot(gs[2]
raw_ws_ds_hp_lp_nf.plot_psd(ax=ax3)
plt.show()
It tells me that I have an invalid syntax.
The following code is working but all plots are superimposed
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3,1)
plt.figure()
ax = plt.axes()
# First plot
raw_egi.plot_psd(ax=ax)
raw_ws_ds_hp_lp.plot_psd(ax=ax)
raw_ws_ds_hp_lp_nf.plot_psd(ax=ax)
plt.show()
Could you tell me ho to plot these 3 figures without superimposing but vertically (one by row). Bellow you will find the figure with the working code (i.e. 3 superimposed plots) Thanks for your help
Here is how I solve the question for 2 plots
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2)
raw_bp.plot_psd(ax=ax[0], show=False)
raw_bp_nf.plot_psd(ax=ax[1], show=False)
ax[0].set_title('PSD before filtering')
ax[1].set_title('PSD after filtering')
ax[1].set_xlabel('Frequency (Hz)')
fig.set_tight_layout(True)
plt.show()
I'm currently having an issue with saving colors and matplotlib. When I run the following code I get the expected result
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
fig.patch.set_facecolor('xkcd:mint green')
plt.show()
Here is a screenshot of what is shown, which is the result I'm expecting.
However, when I run the save function either through python or by manually clicking save on the figure it results in the following image, without the colored borders.
Code to reproduce image above
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
fig.patch.set_facecolor('xkcd:mint green')
# Also doesn't work with fig.savefig
plt.savefig("test.png", dpi=200)
#JohanC pointed out in the comments it takes a face color arguement.
Fixed code
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
# Also doesn't work with fig.savefig
plt.savefig("test.png", facecolor='xkcd:mint green', dpi=200)
I'm attempting to add a legend to overlay an imshow() plot displaying an animated array of random numbers. I want the legend to update to display the step that we are viewing.
I attempted to follow the steps here, which shows how to create an animated legend for subplots() using FuncAnimation. I believe the only way to display animated arrays is using ArtistAnimation() and imshow(), but one or both of these is causing me an issue to follow the linked solution.
I've attached below the working code to generate the animated random array, with the legend solution (from link) double commented out.
Any help or advice to remedy would be enormously appreciated.
Thanks,
C
import matplotlib.animation as animation
from matplotlib import colors
import matplotlib.pyplot as plt
import numpy as np
N=20
steps = 100
interval_pause = 100
repeat_pause = 1000
cmap = colors.ListedColormap(['white', 'black'])
bounds=[-1,0,1]
norm = colors.BoundaryNorm(bounds, cmap.N)
fig = plt.figure()
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.xaxis.set_ticks([])
ax.axes.yaxis.set_ticks([])
#plt.colorbar(img, cmap=cmap, norm=norm, boundaries=bounds, ticks=[-1,0,1])
array = 2*(np.random.rand(N,N,steps)-0.5)
state = np.zeros(steps)
ims = []
##leg = ax.legend(loc='upper left',prop={'size':12})
for step in range(0,steps):
state = array[:,:,step]
im = plt.imshow(state,interpolation='nearest',cmap=cmap,norm=norm, animated=True)
##lab = 'step = '+str(step)
##leg.texts.set_text(lab)
ims.append([im])##+leg])
ani = animation.ArtistAnimation(fig,ims,interval=interval_pause,repeat_delay=repeat_pause)
#ani.save('animate_evolution '+str(timer())+'.mp4')
plt.show()
As shown in the question you link to it is easier to use a FuncAnimation. This allows to simply update a single legend and imshow plot instead of creating several of those.
Because it's not really clear what the legend is supposed to show for an imshow plot, I just created a blue rectangle. You can of course replace it with whatever you like.
import matplotlib.animation as animation
from matplotlib import colors
import matplotlib.pyplot as plt
import numpy as np
N=20
steps = 100
interval_pause = 100
repeat_pause = 1000
cmap = colors.ListedColormap(['white', 'black'])
bounds=[-1,0,1]
norm = colors.BoundaryNorm(bounds, cmap.N)
fig = plt.figure()
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.xaxis.set_ticks([])
ax.axes.yaxis.set_ticks([])
array = 2*(np.random.rand(N,N,steps)-0.5)
leg = ax.legend([plt.Rectangle((0,0),1,1)],["step0"], loc='upper left',prop={'size':12})
img = ax.imshow(array[:,:,0],interpolation='nearest',cmap=cmap,norm=norm, animated=True)
fig.colorbar(img, cmap=cmap, norm=norm, boundaries=bounds, ticks=[-1,0,1])
def update(step):
state = array[:,:,step]
img.set_data(state)
lab = 'step = '+str(step)
leg.texts[0].set_text(lab)
ani = animation.FuncAnimation(fig,update,frames = steps,
interval=interval_pause,repeat_delay=repeat_pause)
plt.show()
I've tried to find a way to copy a 3D figure in matplotlib but I didn't find a solution which is appropriate in my case.
From these posts
How do I reuse plots in matplotlib?
and
How to combine several matplotlib figures into one figure?
Using fig2._axstack.add(fig2._make_key(ax),ax) as in the code below gives quite the good result but figure 2 is not interactive I can't rotate the figure etc :
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(1)
ax = fig.gca(projection = '3d')
ax.plot([0,1],[0,1],[0,1])
fig2 = plt.figure(2)
fig2._axstack.add(fig2._make_key(ax),ax)
plt.show()
An alternative would be to copy objects from ax to ax2 using a copy method proposed in this post How do I reuse plots in matplotlib? but executing the code below returns RuntimeError: Can not put single artist in more than one figure :
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np, copy
fig = plt.figure(1)
ax = fig.gca(projection = '3d')
ax.plot([0,1],[0,1],[0,1])
fig2 = plt.figure(2)
ax2 = fig2.gca(projection = '3d')
for n in range(len(ax.lines)) :
ax2.add_line(copy.copy(ax.lines[n]))
plt.show()
Those codes are pretty simple but I don't want to copy/paste part of my code for drawing similar figures
Thanks in advance for your reply !
I am drawing two subplots with Matplotlib, essentially following :
subplot(211); imshow(a); scatter(..., ...)
subplot(212); imshow(b); scatter(..., ...)
Can I draw lines between those two subplots? How would I do that?
The solution from the other answers are suboptimal in many cases (as they would only work if no changes are made to the plot after calculating the points).
A better solution would use the specially designed ConnectionPatch:
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch
import numpy as np
fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
x,y = np.random.rand(100),np.random.rand(100)
ax1.plot(x,y,'ko')
ax2.plot(x,y,'ko')
i = 10
xy = (x[i],y[i])
con = ConnectionPatch(xyA=xy, xyB=xy, coordsA="data", coordsB="data",
axesA=ax2, axesB=ax1, color="red")
ax2.add_artist(con)
ax1.plot(x[i],y[i],'ro',markersize=10)
ax2.plot(x[i],y[i],'ro',markersize=10)
plt.show()
You could use fig.line. It adds any line to your figure. Figure lines are higher level than axis lines, so you don't need any axis to draw it.
This example marks the same point on the two axes. It's necessary to be careful with the coordinate system, but the transform does all the hard work for you.
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
x,y = np.random.rand(100),np.random.rand(100)
ax1.plot(x,y,'ko')
ax2.plot(x,y,'ko')
i = 10
transFigure = fig.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform([x[i],y[i]]))
coord2 = transFigure.transform(ax2.transData.transform([x[i],y[i]]))
line = matplotlib.lines.Line2D((coord1[0],coord2[0]),(coord1[1],coord2[1]),
transform=fig.transFigure)
fig.lines = line,
ax1.plot(x[i],y[i],'ro',markersize=20)
ax2.plot(x[i],y[i],'ro',markersize=20)
plt.show()
I'm not sure if this is exactly what you are looking for, but a simple trick to plot across subplots.
import matplotlib.pyplot as plt
import numpy as np
ax1=plt.figure(1).add_subplot(211)
ax2=plt.figure(1).add_subplot(212)
x_data=np.linspace(0,10,20)
ax1.plot(x_data, x_data**2,'o')
ax2.plot(x_data, x_data**3, 'o')
ax3 = plt.figure(1).add_subplot(111)
ax3.plot([5,5],[0,1],'--')
ax3.set_xlim([0,10])
ax3.axis("off")
plt.show()