ploting mutliple PSD with mne for python in same figure - python

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

Related

Python Matplotlib doesn't show figure facecolor when saving figure / plot

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)

Showing subplots at each pass of a loop

I would essentially like to do the following:
import matplotlib.pyplot as plt
import numpy as np
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for i in range(10):
ax1.scatter(i, np.sqrt(i))
ax1.show() # something equivalent to this
ax2.scatter(i, i**2)
That is, each time a point is plotted on ax1, it is shown - ax2 being shown once.
You cannot show an axes alone. An axes is always part of a figure. For animations you would want to use an interactive backend. Then the code in a jupyter notebook could look like
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
frames = 10
x = np.arange(frames)
line1, = ax1.plot([],[], ls="", marker="o")
line2, = ax2.plot(x, x**2, ls="", marker="o")
ax2.set_visible(False)
def animate(i):
line1.set_data(x[:i], np.sqrt(x[:i]))
ax1.set_title(f"{i}")
ax1.relim()
ax1.autoscale_view()
if i==frames-1:
ax2.set_visible(True)
fig2.canvas.draw_idle()
ani = FuncAnimation(fig1, animate, frames=frames, repeat=False)
plt.show()
If you want to change plots dynamically I'd suggest you don't redraw the whole plot every time, this will result in very laggy behavior. Instead you could use Blit to do this. I used it in a previous project. Maybe it can help you too if you just take the parts from this you need:
Python project dynamically updating plot

how fix colorbar with different plot

Below I created a simple example of my dataset. I have 4 points and each steps their value change. The points are plotted in x,y positions and the colors change with their value. How i can fix one colorbar useful for each plot?
import pandas as pd
import matplotlib.pyplot as plt
data=[[1,1,3],[1,2,1],[2,1,9],[2,2,0]]
a=pd.DataFrame(data)
a.columns=['x','y','value']
data2=[[1,1,5],[1,2,2],[2,1,1],[2,2,3]]
b=pd.DataFrame(data2)
b.columns=['x','y','value']
data3=[[1,1,15],[1,2,7],[2,1,4],[2,2,8]]
c=pd.DataFrame(data3)
c.columns=['x','y','value']
final=[a,b,c]
for i in range(0,len(final)):
fig, ax = plt.subplots()
plt.scatter(final[i]['x'],final[i]['y'],c=final[i]['value'])
plt.colorbar()
I have one other question, I want to create an animation of these 3 plots (with the same colorbar) but i'm not able to do that, someone can help me?
For the same colorbar add simply: vmin and vmax to plt.scatter. For example:
for i in range(0,len(final)):
fig, ax = plt.subplots()
plt.scatter(final[i]['x'],final[i]['y'],c=final[i]['value'],vmin=0, vmax=15,)
plt.colorbar()
What kind of animation do you desire? Plot the scatters one by one?
this should do:
fig, axs = plt.subplots(1,3, figsize=(12,3))
for i in range(0,len(final)):
im = axs[i].scatter(final[i]['x'],final[i]['y'],c=final[i]['value'])
fig.colorbar(im, ax=axs.ravel().tolist())
more ideas in this thread: Matplotlib 2 Subplots, 1 Colorbar
For animation - need more details.

Matplotlib copy/duplicate a 3D figure?

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 !

How can an existing 2D AxesSubplot object be converted/upgraded to an Axes3DSubplot object?

Assume I have some matplotlib code that looks like the following:
### import statements, etc. ###
ax1 = fig.add_subplot(221)
### plot some 2D data to ax1 ###
ax2 = fig.add_subplot(221, projection='3d')
### plot some 3D data to ax2 ###
The effect of the ax2 = ... line is to remove whatever was plotted to ax1, and to create a new Axes3DSubplot object.
My question is: how can I get an ax2 object (having the same subplot position as ax1 had) which has a 3D projection and which "imports" all of the 2D data that was previously plotted to ax1?
You can plot the data from the 2D-Axes in the corresponding 3D-Axes. Example:
get from this:
plot here:
This is the code used for the above example:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.ion()
ax1 = plt.subplot(221)
ax1.plot([1,2,3,4])
ax2 = plt.subplot(222)
ax2.plot([4,3,2,1])
ax3 = plt.subplot(223)
ax3.plot([4,3,2,1])
ax4 = plt.subplot(224)
ax4.plot([1,2,3,4])
plt.gcf().tight_layout()
plt.show()
plt.figure()
ax1_3d = plt.subplot(221, projection='3d')
ax2_3d = plt.subplot(222, projection='3d')
ax3_3d = plt.subplot(223, projection='3d')
ax4_3d = plt.subplot(224, projection='3d')
[ax1_3d.plot(*ax1.lines[i].get_data()) for i,v in enumerate(ax1.lines)]
[ax2_3d.plot(*ax2.lines[i].get_data()) for i,v in enumerate(ax2.lines)]
[ax3_3d.plot(*ax3.lines[i].get_data()) for i,v in enumerate(ax3.lines)]
[ax4_3d.plot(*ax4.lines[i].get_data()) for i,v in enumerate(ax4.lines)]
plt.gcf().tight_layout()
plt.show()
This is a bit of a resurrection, but I came across this same issue today and found a solution, based mostly off of #Saullo Castro's answer. This example uses one subplot, but the idea is the same no matter how many you have:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Initial 2d axes
ax1 = plt.subplot(111)
ax1.plot([1,2,3,4])
# Create Axes3D and plot the 2d data on it
ax1_3d = plt.subplot(111, projection='3d')
[ax1_3d.plot(*ax1.lines[i].get_data()) for i,v in enumerate(ax1.lines)]
# Important step: turn off the old 2d axes!
ax1.set_axis_off()
plt.show()

Categories