I have a code like this, and it will present a figure with the x-axis from 1 to 200, and the y-axis also from 1 to 200. But I would like to make the two axes both from -1.5 to 1.5 with 0.5 space.
I have already tried "plt.xticks" and "set_xlim", but I still cannot make it.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.stats import multivariate_normal
fig, main_ax = plt.subplots(figsize=(5, 5))
divider = make_axes_locatable(main_ax)
top_ax = divider.append_axes("top", 1.05, pad=0.1,sharex=main_ax)
top_ax.xaxis.set_tick_params(labelbottom=False)
main_ax.set_xlabel('dim 1')
main_ax.set_ylabel('dim 2')
top_ax.set_ylabel('Z profile')
x, y = np.mgrid[-1:1:.01, -1:1:.01]
pos = np.empty(x.shape + (2,))
pos[:, :, 0] = x; pos[:, :, 1] = y
rv = multivariate_normal([-0.2, 0.2], [[1, 1.5], [0.25, 0.25]])
z = rv.pdf(pos)
z_max = z.max()
plt.set_cmap(plt.cm.gist_earth)
cur_x = 100
cur_y = 100
main_ax.imshow(z, origin='lower')
main_ax.autoscale(enable=False)
top_ax.autoscale(enable=False)
top_ax.set_ylim(top=z_max)
v_line = main_ax.axvline(cur_x, color='r')
h_line = main_ax.axhline(cur_y, color='y')
v_prof, = top_ax.plot(np.arange(x.shape[1])[::-1], z[:,int(cur_x)], 'r-')
h_prof, = top_ax.plot(np.arange(x.shape[0]), z[int(cur_y),:], 'y-')
plt.show()
You can simply use this code.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.stats import multivariate_normal
fig, main_ax = plt.subplots(figsize=(5, 5))
divider = make_axes_locatable(main_ax)
top_ax = divider.append_axes("top", 1.05, pad=0.1,sharex=main_ax)
top_ax.xaxis.set_tick_params(labelbottom=False)
main_ax.set_xlabel('dim 1')
main_ax.set_ylabel('dim 2')
top_ax.set_ylabel('Z profile')
x, y = np.mgrid[-1:1:.01, -1:1:.01]
pos = np.empty(x.shape + (2,))
pos[:, :, 0] = x; pos[:, :, 1] = y
rv = multivariate_normal([-0.2, 0.2], [[1, 1.5], [0.25, 0.25]])
z = rv.pdf(pos)
z_max = z.max()
plt.set_cmap(plt.cm.gist_earth)
# For y axis
main_ax.set_yticks(np.linspace(0,200,7))
main_ax.set_yticklabels(np.linspace(-1.5,1.5,7))
# For x axis
plt.xticks(np.linspace(0,200,7),np.linspace(-1.5,1.5,7))
cur_x = 100
cur_y = 100
main_ax.imshow(z, origin='lower')
main_ax.autoscale(enable=False)
top_ax.autoscale(enable=False)
top_ax.set_ylim(top=z_max)
v_line = main_ax.axvline(cur_x, color='r')
h_line = main_ax.axhline(cur_y, color='y')
v_prof, = top_ax.plot(np.arange(x.shape[1])[::-1], z[:,int(cur_x)], 'r-')
h_prof, = top_ax.plot(np.arange(x.shape[0]), z[int(cur_y),:], 'y-')
Related
I am plotting a graph using matplotlib.
Here is the code:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_title("Grid search results - " + model_name)
ax.set_xlabel("Log10(Wight decay)")
ax.set_ylabel("Log10(Learning rate)")
ax.set_zlabel("Batch size")
ax.set_xticks(weightdecay)
ax.set_yticks(learningrate)
ax.set_zticks(trainbatchsize)
scat_plot = ax.scatter(xs=weightdecay, ys=learningrate, zs=trainbatchsize, c=f1, cmap="bwr")
ax.text(top_score[0], top_score[1], top_score[2], top_score[3], color="black")
cb = plt.colorbar(scat_plot, pad=0.2)
cb.ax.set_xlabel('F1 score')
plt.plot(top_score[0], top_score[1], top_score[2], marker="o", markersize=15, markerfacecolor="yellow")
path = Path(output_dir)
plt.savefig(str(path.absolute()) + '/grid_search_plot_' + model_name + ".pdf")
plt.show()
The graph I am getting looks like:
What I would like to do is to use a more granular color-bar. For example for my F1-score (colour-bar), show in:
color1 scores < 0.5
color2 scores 0.5 - 0.75
color3 scores 0.75 - 0.80
color4 scores 0.8 - 0.85
color5 scores 0.85-1
I was trying to re-use some code to create a custom cmap but nothing was working as expected.
One cheap/quick solution might be to create a "categorical color value", like this:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import ListedColormap
import numpy as np
N = 40
x = np.random.uniform(0, 1, N)
y = np.random.uniform(0, 1, N)
z = np.random.uniform(0, 1, N)
# color values
c = np.random.uniform(0, 1, N)
# new color values
new_col = c.copy()
new_col[c < 0.5] = 0
new_col[(c >= 0.5) & (c < 0.75)] = 1
new_col[(c >= 0.75) & (c < 0.8)] = 2
new_col[(c >= 0.8) & (c < 0.85)] = 3
new_col[c >= 0.85] = 4
new_col = new_col / new_col.max()
fig = plt.figure()
ax = fig.add_subplot(projection="3d")
scatter = ax.scatter(x, y, z, c=new_col, cmap=cm.get_cmap("tab10", 5))
cb = fig.colorbar(scatter)
cb.ax.set_yticklabels([0, 0.5, 0.75, 0.80, 0.85, 1])
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
EDIT to accommodate comments. The following should be able to deal with cases in which a category doesn't have any element:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import ListedColormap
import numpy as np
N = 40
x = np.random.uniform(0, 1, N)
y = np.random.uniform(0, 1, N)
z = np.random.uniform(0, 1, N)
# color values
c = np.random.uniform(0, 1, N)
# number of categories
NC = 5
# new color values
new_col = c.copy()
new_col[c < 0.5] = 0
new_col[(c >= 0.5) & (c < 0.75)] = 1
new_col[(c >= 0.75) & (c < 0.8)] = 2
new_col[(c >= 0.8) & (c < 0.85)] = 3
new_col[c >= 0.85] = 4
new_col = new_col / NC
fig = plt.figure()
ax = fig.add_subplot(projection="3d")
cmap = ListedColormap(["red", "green", "blue", "magenta", "cyan"])
scatter = ax.scatter(x, y, z, c=cmap(new_col))
cb = fig.colorbar(cm.ScalarMappable(cmap=cmap))
cb.ax.set_yticks(np.linspace(0, 1, NC+1), [0, 0.5, 0.75, 0.80, 0.85, 1])
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
How can I create in python a bi-variate data plot with "vertical" marginal histograms like this?:
Say that the data is generated via:
from scipy.stats import multivariate_normal
import numpy as np
mean = np.array([0, 0])
cov = np.array([[1, 0.5], [0.5, 2]])
data = multivariate_normal(mean, cov).rvs(1000)
Here is sample code which shows how one can do this:
import math
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rc, rcParams
from numpy.linalg import eigh
from scipy.stats import multivariate_normal, norm
from mpl_toolkits.mplot3d import Axes3D
rcParams['text.latex.preamble'] = r'\boldmath'
rc('text', usetex=True)
mean = np.array([0,0])
cov = np.array([[1, 0.3], [0.3, .5]])
np.random.seed(0)
mvn_rvs = multivariate_normal(mean, cov).rvs(800)
pdf_x = norm(mean[0], np.sqrt(cov[0,0])).pdf
pdf_y = norm(mean[1], np.sqrt(cov[1,1])).pdf
rv_x = mvn_rvs[:, 0]
rv_y = mvn_rvs[:, 1]
x = np.linspace(-3, 3, 101)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
fontsize = 30
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1.15, 1.15, 1, 1]))
ax.plot(y, pdf_y(y), zs=x.min(), zdir='x', linewidth=3, label="$\\mathsf{P_y(y)}$")
ax.plot(x, pdf_x(x), zs=y.max(), zdir='y', linewidth=3, label='$\\mathsf{P_x(x)}$')
leg = plt.legend(fontsize=fontsize, ncol=2, frameon=False, bbox_to_anchor=(-0.10, 1.1275),
loc='upper left', handlelength=0.7, handletextpad=0.5, columnspacing=2.4)
grid_linewidth = 1.15
ax.xaxis._axinfo["grid"]['linewidth'] = grid_linewidth
ax.yaxis._axinfo["grid"]['linewidth'] = grid_linewidth
ax.zaxis._axinfo["grid"]['linewidth'] = grid_linewidth
ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.w_xaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
ax.w_yaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
ax.w_zaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
labelpad = -5
ax.set_xlabel("$\\mathsf{x}$", fontsize=fontsize, labelpad=labelpad)
ax.set_ylabel("$\\mathsf{y}$", fontsize=fontsize, labelpad=labelpad)
labelsize = 10
ax.xaxis.set_rotate_label(False)
ax.yaxis.set_rotate_label(False)
ax.set_zlim(bottom=0)
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
ax.xaxis.set_ticklabels([])
ax.xaxis.set_visible(False)
ax.yaxis.set_ticklabels([])
ax.zaxis.set_ticklabels([])
sx2 = cov[0, 0]
sy2 = cov[1, 1]
rho = cov[0, 1] / np.sqrt(sx2 * sy2)
Sigma = cov
target = 0.1
gamma = math.log(1 / (4*(np.pi**2)*(sx2**2)*(sy2**2)*(1 - rho**2)*(target**2)))
eigenvalues, P = eigh(np.linalg.inv(Sigma))
# Compute u and v as per link using thetas from 0 to 2pi
thetas = np.linspace(0, 2*np.pi, 10000)
uv = (np.sqrt(gamma) / np.sqrt(eigenvalues)) * np.hstack((np.cos(thetas).reshape(-1,1), np.sin(thetas).reshape(-1, 1)))
orig_coord=np.zeros((10000,2))
for i in range(len(uv)):
orig_coord[i,0]=np.matmul(np.linalg.inv(P), uv[i,:])[0]
orig_coord[i,1]=np.matmul(np.linalg.inv(P), uv[i,:])[1]
ax.plot(rv_x, rv_y, 0*rv_x, ' o', c='g', markersize=1.1) # "RdBu_r")
ax.plot(orig_coord[:, 0], orig_coord[:, 1],
0 * np.ones_like(orig_coord[:, 0]), c='r', linewidth=3)
ax.view_init(azim=-45, elev=20)
I am trying to replicate this type of plot (heatmap with colorbars as leaves)
This is what I've done so far
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
import scipy.cluster.hierarchy as sch
import scipy.spatial.distance as ssd
#read data
fid_df = pd.read_csv(fid_file, index_col=[0])
# scale data
def scale(x):
return np.math.log2(x+1)
fid_df = fid_df.applymap(scale)
# clustering colums
data_1D_X = ssd.pdist(fid_df.T, 'euclidean')
X = sch.linkage(data_1D_X, method='ward')
# clustering rows
data_1D_Y = ssd.pdist(fid_df, 'cityblock')
Y = linkage(data_1D_Y, method='ward')
#plot first dendrogram
fig = plt.figure(figsize=(8, 8))
ax1 = fig.add_axes([0.09, 0.1, 0.2, 0.6])
Z1 = sch.dendrogram(Y, orientation='left')
ax1.set_xticks([])
ax1.set_yticks([])
# second dendrogram.
ax2 = fig.add_axes([0.3, 0.71, 0.6, 0.2])
Z2 = sch.dendrogram(X)
ax2.set_xticks([])
ax2.set_yticks([])
# plot matrix
axmatrix = fig.add_axes([0.3, 0.1, 0.6, 0.6])
# sorts based of clustering
idx1 = Z1['leaves']
idx2 = Z2['leaves']
D = fid_df.values[idx1, :]
D = D[:, idx2]
im = axmatrix.matshow(D, aspect='auto', origin='lower', cmap=plt.cm.YlGnBu)
axmatrix.set_xticks([])
axmatrix.set_yticks([])
Example:
However, I need to add colorbars that would show the initial groups of rows and columns. Any idea how to do this?
Something like this?
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax1 = fig.add_axes((0, 0, 1, 0.9))
ax2 = fig.add_axes((0, 0.9, 1, 0.1))
gridY, gridX = np.mgrid[0:10:11 * 1j, 0:10:11 * 1j]
ax1.pcolormesh(gridX, gridY, np.sqrt(gridX ** 2 + gridY ** 2))
randCol = ['red', 'blue']
for value in np.linspace(0, 10, 1001):
ax2.axvline(value, color=randCol[np.random.default_rng().integers(2)])
ax2.set_xlim((0, 10))
ax2.tick_params(labelbottom=False, bottom=False, labelleft=False, left=False)
fig.savefig('so.png', bbox_inches='tight')
I have an array of shape(512,512).
Looks like, (row=x, column=y, density=z=the number of the array)
[[0.012825 0.020408 0.022976 ... 0.015938 0.02165 0.024357]
[0.036332 0.031904 0.025462 ... 0.031095 0.019812 0.024523]
[0.015831 0.027392 0.031939 ... 0.016249 0.01697 0.028686]
...
[0.024545 0.011895 0.022235 ... 0.033226 0.03223 0.030235]]
I had already drawn it into a 2D density plot. My goal is to find the center of the circle and draw a vertical and horizontal cross-section in one figure.
Now, I have the trouble to find the center of the circle and combine two cross-sections in one figure.
Please help.
This is my code:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy.ndimage
data = pd.read_csv('D:/BFP.csv', header=None)
# create data
data = np.array(data)
print(data)
#plot data
side = np.linspace(-1.5,1.5,512)
x,y = np.meshgrid(side,side)
z = [[data[i][j] for i in range(len(data[0]))]for j in range(len(data))]
#-- Extract the line...
# Make a line with "num" points...
x0, y0 = 270, 0 # These are in _pixel_ coordinates!!
x1, y1 = 270, 500
num = 512
x_, y_ = np.linspace(x0, x1, num), np.linspace(y0, y1, num)
# Extract the values along the line, using cubic interpolation
zi = scipy.ndimage.map_coordinates(z, np.vstack((x_,y_)))
#-- Plot...
fig, axes = plt.subplots(nrows=2)
axes[0].imshow(z,origin='lower')
axes[0].plot([x0, x1], [y0, y1], 'ro-')
#axes[0].axis('image')
axes[1].plot(zi)
plt.savefig('D:/vertical.png')
plt.show()
image here:
I cannot help you with finding the center of the circle, but you can create a nice visualization of the cross section by creating 3 axes in a grid. Usually, I would use GridSpec for this, but imhsow has a tendency to mess up the relative size of the axes to maintain square pixels. Thankfully, the AxesGrid toolkit can help.
The base of the code is inspired by this matplotlib example.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.stats import multivariate_normal
import scipy
fig, main_ax = plt.subplots(figsize=(5, 5))
divider = make_axes_locatable(main_ax)
top_ax = divider.append_axes("top", 1.05, pad=0.1, sharex=main_ax)
right_ax = divider.append_axes("right", 1.05, pad=0.1, sharey=main_ax)
# make some labels invisible
top_ax.xaxis.set_tick_params(labelbottom=False)
right_ax.yaxis.set_tick_params(labelleft=False)
main_ax.set_xlabel('dim 1')
main_ax.set_ylabel('dim 2')
top_ax.set_ylabel('Z profile')
right_ax.set_xlabel('Z profile')
x, y = np.mgrid[-1:1:.01, -1:1:.01]
pos = np.empty(x.shape + (2,))
pos[:, :, 0] = x; pos[:, :, 1] = y
rv = multivariate_normal([-0.2, 0.2], [[1, 1.5], [0.25, 0.25]])
z = rv.pdf(pos)
z_max = z.max()
cur_x = 110
cur_y = 40
main_ax.imshow(z, origin='lower')
main_ax.autoscale(enable=False)
right_ax.autoscale(enable=False)
top_ax.autoscale(enable=False)
right_ax.set_xlim(right=z_max)
top_ax.set_ylim(top=z_max)
v_line = main_ax.axvline(cur_x, color='r')
h_line = main_ax.axhline(cur_y, color='g')
v_prof, = right_ax.plot(z[:,int(cur_x)],np.arange(x.shape[1]), 'r-')
h_prof, = top_ax.plot(np.arange(x.shape[0]),z[int(cur_y),:], 'g-')
plt.show()
Just for fun, you can even make it interactive
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.stats import multivariate_normal
import scipy
fig, main_ax = plt.subplots(figsize=(5, 5))
divider = make_axes_locatable(main_ax)
top_ax = divider.append_axes("top", 1.05, pad=0.1, sharex=main_ax)
right_ax = divider.append_axes("right", 1.05, pad=0.1, sharey=main_ax)
# make some labels invisible
top_ax.xaxis.set_tick_params(labelbottom=False)
right_ax.yaxis.set_tick_params(labelleft=False)
main_ax.set_xlabel('dim 1')
main_ax.set_ylabel('dim 2')
top_ax.set_ylabel('Z profile')
right_ax.set_xlabel('Z profile')
x, y = np.mgrid[-1:1:.01, -1:1:.01]
pos = np.empty(x.shape + (2,))
pos[:, :, 0] = x; pos[:, :, 1] = y
rv = multivariate_normal([-0.2, 0.2], [[1, 1.5], [0.25, 0.25]])
z = rv.pdf(pos)
z_max = z.max()
main_ax.imshow(z, origin='lower')
main_ax.autoscale(enable=False)
right_ax.autoscale(enable=False)
top_ax.autoscale(enable=False)
right_ax.set_xlim(right=z_max)
top_ax.set_ylim(top=z_max)
v_line = main_ax.axvline(np.nan, color='r')
h_line = main_ax.axhline(np.nan, color='g')
v_prof, = right_ax.plot(np.zeros(x.shape[1]),np.arange(x.shape[1]), 'r-')
h_prof, = top_ax.plot(np.arange(x.shape[0]),np.zeros(x.shape[0]), 'g-')
def on_move(event):
if event.inaxes is main_ax:
cur_x = event.xdata
cur_y = event.ydata
v_line.set_xdata([cur_x,cur_x])
h_line.set_ydata([cur_y,cur_y])
v_prof.set_xdata(z[:,int(cur_x)])
h_prof.set_ydata(z[int(cur_y),:])
fig.canvas.draw_idle()
fig.canvas.mpl_connect('motion_notify_event', on_move)
plt.show()
NB: the lag is just due to the convertion in gif, the update is much smoother on my machine
I'm creating the heat map of a function with tuneable exponent. Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
from matplotlib.colors import LogNorm
alpha0 = 2.
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
bining = np.logspace(1, 10, 1000)
x = y = bining
X, Y = np.meshgrid(x, y)
Z = [[0 for i in xrange(len(x) - 1)] for j in xrange(len(y) - 1) ]
for i in xrange(len(x) - 1):
for j in xrange(len(y) - 1):
Z[i][j] = 1./((x[i]+y[j])**(2+alpha0))
Z = np.array(Z)
im = plt.pcolormesh(X,Y,Z, cmap = plt.cm.Spectral, norm=LogNorm())
plt.xscale('log')
plt.yscale('log')
plt.axes().set_aspect('equal')
axcolor = 'lightgoldenrodyellow'
axexp = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
sexp = Slider(axexp, r"$\alpha$", 0.1, 10.0, valinit=alpha0)
def update(val):
alpha = sexp.val
Z = [[0 for i in xrange(len(x) - 1)] for j in xrange(len(y) - 1) ]
for i in xrange(len(x) - 1):
for j in xrange(len(y) - 1):
Z[i][j] = 1./((x[i]+y[j])**(2+alpha))
Z = np.array(Z)
plt.pcolormesh(X,Y,Z, cmap = plt.cm.Spectral, norm=LogNorm())
fig.canvas.draw_idle()
sexp.on_changed(update)
It creates the figure and the slider, but when I try to change the exponent value, the heat map is not affected.
So my question, why is it not working and how can I solve it ? Also, widgets can be saved ? In what format ? Eventually I would use in a Beamer (LaTeX) presentation.
Thank you !