How do I make a multi panel plot like this? - python

I have tried using gridspec, everything looks fine but mi main plot doesn't fill all the space.
[1]: https://i.stack.imgur.com/frHEN.png
[2]: https://i.stack.imgur.com/MA1Sg.png
This is my code:
import h5py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import transforms
from matplotlib.transforms import Affine2D
import matplotlib.gridspec as gridspec
from FUNCION import *
from FUNCIONAVG import *
f = h5py.File('Datos1', 'r')
list(f.keys())
print(f.keys());
data=f['default'];
data=np.array(data)
fig = plt.figure(1, figsize=(5, 5))
gs = gridspec.GridSpec(8, 8)
gs.update(wspace=0, hspace=0)
xtr_subplot = fig.add_subplot(gs[0:6, 0:2])
base = plt.gca().transData
rot = transforms.Affine2D().rotate_deg(90)
line = plt.plot(sum, transform=rot + base)
plt.ylabel("Y Label")
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[0:6, 2:6])
plt.imshow(data, aspect=(6/4))
ax = plt.gca()
ax.axes.yaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[6:8, 2:6])
plt.plot(avg)
plt.savefig("multipanel.png")
plt.show()

Set the aspect argument of plt.imshow.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec
from matplotlib import transforms
data = np.random.randn(100).reshape(10, 10)
avg = np.random.randn(10)
total = np.random.randn(10)
fig = plt.figure(1, figsize=(5, 5))
gs = gridspec.GridSpec(8, 8)
gs.update(wspace=0, hspace=0)
xtr_subplot = fig.add_subplot(gs[0:6, 0:2])
base = plt.gca().transData
rot = transforms.Affine2D().rotate_deg(90)
line = plt.plot(total, transform=rot + base)
plt.ylabel("Y Label")
ax = plt.gca()
ax.axes.xaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[0:6, 2:6])
plt.imshow(data, aspect=(6 / 4))
ax = plt.gca()
ax.axes.yaxis.set_ticklabels([])
xtr_subplot = fig.add_subplot(gs[6:8, 2:6])
plt.plot(avg)
plt.savefig("multipanel.png")

Related

How to change border color of violin plot in pandas graph?

I want to change the color of lineborder of violinplots.
I can set lines.linewidth to 0 but I want to show borders not to hide them. How to change the color of the border?
sns.set_context("paper", rc={"lines.linewidth": 0.8})
My code is as follows:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
import numpy as np
datasets = pd.read_csv("merged.csv", index_col=0);
df = datasets
df.protocol = df.protocol.astype(str)
f, ax = plt.subplots(figsize=(18, 6))
sns.violinplot(x="time",
y="values",
hue="protocol",
data=df,
bw=.5,
scale="count"
)
sns.despine(left=True)
f.suptitle('Title', fontsize=22, fontweight='bold')
ax.set_xlabel("Time",size = 16,alpha=0.7)
ax.set_ylabel("Values",size = 16,alpha=0.7)
ax.set_xticklabels(df.qber, rotation=90)
ax.grid(True)
plt.legend(loc='upper right')
plt.grid(linestyle='--', alpha=0.7)
fig = ax.get_figure()
fig.savefig('time_v.pdf', bbox_inches='tight')
Thank you!
this should be very close to what you're looking for:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
import numpy as np
def patch_violinplot(palette, n):
from matplotlib.collections import PolyCollection
ax = plt.gca()
violins = [art for art in ax.get_children() if isinstance(art, PolyCollection)]
colors = sns.color_palette(palette, n_colors=n) * (len(violins)//n)
for i in range(len(violins)):
violins[i].set_edgecolor(colors[i])
datasets = pd.read_csv("merged.csv", index_col=0);
df = datasets
df.protocol = df.protocol.astype(str)
num_cols = df['protocol'].nunique()
f, ax = plt.subplots(figsize=(18, 6))
sns.violinplot(x="time",
y="values",
hue="protocol",
data=df,
bw=.5,
scale="count",
palette="deep"
)
patch_violinplot("deep", num_cols)
sns.despine(left=True)
f.suptitle('Title', fontsize=22, fontweight='bold')
ax.set_xlabel("Time",size = 16,alpha=0.7)
ax.set_ylabel("Values",size = 16,alpha=0.7)
ax.set_xticklabels(df.qber, rotation=90)
ax.grid(True)
plt.legend(loc='upper right')
plt.grid(linestyle='--', alpha=0.7)
fig = ax.get_figure()
fig.savefig('time_v.pdf', bbox_inches='tight')
The patch_violin function came from here.

In python, how to correctly use `colorbar` and `pcolormesh`?

Here is my code,
from mpl_toolkits.axes_grid1 import make_axes_locatable # colorbar
from matplotlib import pyplot as plt
from matplotlib import cm # 3D surface color
import numpy as np
data1 = np.random.rand(10, 12)
data2 = np.random.rand(10, 12)
data3 = data1 - data2
vmin = min([data1.min(), data2.min(), data3.min()])
vmax = max([data1.max(), data2.max(), data2.max()])
fig, (ax_1, ax_2, ax_error) = plt.subplots(nrows=3, ncols=1, figsize=(6, 6))
ax_1.set_ylabel('x')
mesh_1 = ax_1.pcolormesh(data1.T, cmap = cm.coolwarm)
ax_2.set_ylabel('x')
mesh_2 = ax_2.pcolormesh(data2.T, cmap = cm.coolwarm)
mesh_error = ax_error.pcolormesh(data3.T, cmap = cm.coolwarm)
ax_error.set_ylabel('x')
ax_error.set_xlabel('t')
divider = make_axes_locatable(ax_2)
cax_val = divider.append_axes("right", size="2%", pad=.1)
fig.colorbar(mesh_2, ax=[ax_1, ax_2, ax_error], cax=cax_val)
fig.tight_layout()
plt.show()
and it produces an image
However, what I expect is that it produces the picture below
Can anyone help me with this problem? Thanks in advance for any helpful suggestion!
tight_layout doesn't help with this problem, unfortunately. No tight_layout and no axes_grid works fine:
from matplotlib import pyplot as plt
from matplotlib import cm # 3D surface color
import numpy as np
data1 = np.random.rand(10, 12)
data2 = np.random.rand(10, 12)
data3 = data1 - data2
fig, (ax_1, ax_2, ax_error) = plt.subplots(nrows=3, ncols=1, figsize=(6, 6))
mesh_1 = ax_1.pcolormesh(data1.T, cmap = cm.coolwarm)
mesh_2 = ax_2.pcolormesh(data2.T, cmap = cm.coolwarm)
mesh_error = ax_error.pcolormesh(data3.T, cmap = cm.coolwarm)
fig.colorbar(mesh_2, ax=[ax_1, ax_2, ax_error])
plt.show()
If you want better spacing you can try constrained_layout:
fig, (ax_1, ax_2, ax_error) = plt.subplots(nrows=3, ncols=1, figsize=(6, 6),
constrained_layout=True)
Constrained layout will also work for just one axes:
fig.colorbar(mesh_2, ax=ax_2)
With the help from #JodyKlymak, I finally solved the problem. The keypoint lies in using shrink, i.e. fig.colorbar(mesh_2, ax=[ax_1, ax_2, ax_error], shrink=0.3). Here is the solution
from matplotlib import pyplot as plt
from matplotlib import cm # 3D surface color
import numpy as np
data1 = np.random.rand(10, 12)
data2 = np.random.rand(10, 12)
data3 = data1 - data2
fig, (ax_1, ax_2, ax_error) = plt.subplots(nrows=3, ncols=1, figsize=(6, 6))
mesh_1 = ax_1.pcolormesh(data1.T, cmap = cm.coolwarm)
mesh_2 = ax_2.pcolormesh(data2.T, cmap = cm.coolwarm)
mesh_error = ax_error.pcolormesh(data3.T, cmap = cm.coolwarm)
fig.colorbar(mesh_2, ax=[ax_1, ax_2, ax_error], shrink=0.3)
plt.show()
and it produces

Generate heat map from a given data set

In the following heat map, I want to start y values from 0 to 25. Now it is in the reverse direction.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
import matplotlib
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{amsmath}"]
a=[]
for i in range(25):
b=[]
for j in range(25):
b.append(i*j)
a.append(b)
fig = plt.figure(figsize=(8,5.00))
plt.imshow(a, interpolation='nearest')
plt.colorbar()
ax = fig.add_subplot(1,1,1)
major_ticks = np.arange(0, 24, 2)
minor_ticks = np.arange(0, 24, 1)
ax.set_xticks(major_ticks)
ax.set_xticks(minor_ticks, minor=True)
plt.xlabel(r'$\pmb{u} \ \longrightarrow$' )
plt.ylabel(r'$\pmb{v} \ \longrightarrow$')
plt.show()
fig.savefig('abc.eps', bbox_inches = 'tight',
pad_inches = 0.2)
Need to include origin='lower'

Matplotlib : the colorbar keeps shrinking

I wrote a code where I have an array called array2 with numbers between 0. and 1. in it. When I click on the array displayed by imshow the cells in the array take the value 2. and become red.
Then I added a colorbar but it kept shrinking once I clicked on it and the cells didn't become red.
What am I doing wrong ?
Code without colorbar (works fine)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib import cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
from random import random
def test(n):
array1 = np.zeros((n,n))
for i in range(n):
for j in range(n):
array1[i,j] = random()
return array1
# Array
global array2
array2 = test(10)
# Colormap
greens = cm.Greens(np.linspace(0,1, num=50))
greensfill = cm.Greens(np.ones(25))
red = [(1,0,0,1)]*len(greens)
gray = [(.5,.5,.5,1)]*len(greens)
colors = np.vstack((greens, greensfill, red, gray))
mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)
# Matplotlib
fig, axes = plt.subplots(1)
fig.tight_layout()
plt.imshow(array2, animated=True, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5, origin='lower')
def onclick(event):
global x, y
x, y = int(event.xdata), int(event.ydata)
array2[y,x] = 2.
plt.imshow(array2, animated=True, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5, origin='lower')
fig.canvas.mpl_connect('button_press_event', onclick)
Code with colorbar (doesn't work)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib import cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
from random import random
def test(n):
array1 = np.zeros((n,n))
for i in range(n):
for j in range(n):
array1[i,j] = random()
return array1
# Array
global array2
array2 = test(10)
# Colormap
greens = cm.Greens(np.linspace(0,1, num=50))
greensfill = cm.Greens(np.ones(25))
red = [(1,0,0,1)]*len(greens)
gray = [(.5,.5,.5,1)]*len(greens)
colors = np.vstack((greens, greensfill, red, gray))
mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)
# Matplotlib
fig, axes = plt.subplots(1)
fig.tight_layout()
im = plt.imshow(array2, animated=True, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5, origin='lower')
divider = make_axes_locatable(axes)
cax = divider.append_axes("right", size="13%", pad=0.2)
cb = plt.colorbar(im, cax=cax, boundaries=np.linspace(0,1, num=100), ticks=[0,1])
cb.set_label("Title", fontsize=15, labelpad=-5, y=0.5)
def onclick(event):
global x, y
x, y = int(event.xdata), int(event.ydata)
array2[y,x] = 2.
im = plt.imshow(array2, animated=True, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5, origin='lower')
divider = make_axes_locatable(axes)
cax = divider.append_axes("right", size="13%", pad=0.2)
cb = plt.colorbar(im, cax=cax, boundaries=np.linspace(0,1, num=100), ticks=[0,1])
cb.set_label("Title", fontsize=15, labelpad=-5, y=0.5)
fig.canvas.mpl_connect('button_press_event', onclick)
It would be better to just update the imshow, instead of drawing a new one every time a click is performed. This can be done using the .set_data() method. The advantage is that the colorbar can stay where it is and doesn't get touched.
In general it's best to work with the plotting objects directly instead of pyplot when doing interactive stuff. So using fig and ax instead of plt in most cases.
Note that to accurately catch the click on a pixel you need to round the coordinate first, int(np.round(event.xdata)).
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib import cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
global array2
array2 = np.random.rand(10,10)
# Colormap
greens = cm.Greens(np.linspace(0,1, num=50))
greensfill = cm.Greens(np.ones(25))
red = [(1,0,0,1)]*len(greens)
gray = [(.5,.5,.5,1)]*len(greens)
colors = np.vstack((greens, greensfill, red, gray))
mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)
# Matplotlib
fig, ax = plt.subplots()
fig.tight_layout()
im = ax.imshow(array2, animated=True, cmap = mycmap, interpolation="none",
vmin=0, vmax=3.5, origin='lower')
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="13%", pad=0.2)
cb = fig.colorbar(im, ax =ax, cax=cax, boundaries=np.linspace(0,1, num=100),
ticks=[0,1])
cb.set_label("Title", fontsize=15, labelpad=-5, y=0.5)
def onclick(event):
x, y = int(np.round(event.xdata)), int(np.round(event.ydata))
array2[y,x] = 2.
im.set_data(array2)
fig.canvas.draw_idle()
fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()

How to hatch PolyCollection instance?

Is it possible to hatch PolyCollection instance?
I want to hath a PolyCollection returned from fill_betweenx.
import matplotlib.mlab as mlab
from matplotlib.pyplot import figure, show
import numpy as np
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 1.2*np.sin(4*np.pi*x)
fig = figure()
ax1 = fig.add_subplot(111)
PC = ax1.fill_betweenx(x, 0, y1)
# I want to do something like this
# PC.set_hatch('\')
# but there is no such method
show()
It's a bit of a hack, but you should be able to do something like this:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import PathPatch
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 1.2*np.sin(4*np.pi*x)
fig, ax = plt.subplots()
pc = ax.fill_betweenx(x, 0, y1, color='blue')
# Now we'll add the hatches...
for path in pc.get_paths():
patch = PathPatch(path, hatch='/', facecolor='none')
ax.add_patch(patch)
plt.show()

Categories