Matplotlib copy/duplicate a 3D figure? - python

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 !

Related

ploting mutliple PSD with mne for python in same figure

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()

Generate more plots separate in figure in one script in python

First of all, I apologies if this question was already asked and answered, I haven't found anything really specific about this so if you did, please share and I will delete this post.
What I would like to do is simply generate more separate plots after one another in separate figure in python, because I have an exercise sheet and the a) is to plot a poisson distribution and the b) is to plot a binomial distribution and so ever with c) and d), and I would like that the plots are gathered together in the same script but in separate figure.
I tried as simple as create a sin(x) and a cos(x) plot after one another but it didn't work, the sin and cos were displaying in the same plot.. My code was:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = plt.plot(np.sin(x))
ax2 = plt.plot(np.cos(x))
ax1.set_xlabel('Time (s)')
ax1.set_title('sin')
ax1.legend()
ax2.set_xlabel('Time (s)')
ax2.set_title('cos')
ax2.legend()
plt.show()
Could anyone help me ?
How about this?
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100)
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212, sharex=ax1)
ax1.plot(np.sin(x))
ax2.plot(np.cos(x))
plt.show()
I suggest you should read a simple tutorial about subplots.
EDIT:
To create separate figures:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100)
plt.figure()
plt.plot(np.sin(x))
plt.figure()
plt.plot(np.cos(x))
plt.show()

Invert y axis on matplotlib trisurf 3d graph python

I'm using matplotlib to produce a 3d trisurf graph. I have everything working except that I would like to invert the y-axis, so that the origin is 0,0 not 0,100. I've looked through the matplotlib axes3d API and cannot figure out how to do this. Here is my code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
# my data, xs=xaxis, ys=yaxis, zs=zaxis
mortar_xs = []
cycles_ys = []
score_zs = []
#... populate my data for the 3 arrays: mortar_xs, cycles_ys, score_zs
# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(mortar_xs,cycles_ys,score_zs,cmap=cm.coolwarm)
ax.set_zlim(bottom=0.0,top=1.0)
ax.legend()
ax.set_xlabel("# Mortar")
ax.set_ylabel("# Goals")
ax.set_zlabel("# Score")
plt.show()
My graph produced is the following, but I need the '# Goals' or the y-axis inverted, so that the origin is 0,0 not 0,100. If possible, I would like to do this without changing my data.
tmdavison's comment is what I was looking for:
ax.set_ylim(0,100)
Or
ax.set_ylim(100,0)
The simplest method would be to use ax.invert_yaxis()

Two different plots from same loop in matplotlib?

I would specifically like to create two different plots using one single loop. One plot should have four straight lines from x-y, and another plot should have four angled lines from x-y2. My code only shows everything in a single plot. I don't quite understand how plt works, how can I create two distinct plt objects?
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt2
x=[[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
y=[[1,2,3,4],[2,3,4,5],[3,4,5,6],[7,8,9,10]]
y2=[[11,12,13,24],[42,33,34,65],[23,54,65,86],[77,90,39,54]]
colours=['r','g','b','k']
for i in range(len(x)):
plt.plot(x[i],y2[i],colours[i])
plt2.plot(x[i],y[i],colours[i])
plt.show()
plt2.show()
Is that what you want to do?
import matplotlib.pyplot as plt
x=[[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
y=[[1,2,3,4],[2,3,4,5],[3,4,5,6],[7,8,9,10]]
y2=[[11,12,13,24],[42,33,34,65],[23,54,65,86],[77,90,39,54]]
colours=['r','g','b','k']
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for i in range(len(x)):
ax1.plot(x[i],y2[i],colours[i])
ax2.plot(x[i],y[i],colours[i])
fig1.show()
fig2.show()

Drawing lines between two plots in Matplotlib

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()

Categories