I need to add colorbar on my voxel, where the facecolors base on a array (in my case, the facecolors base on "data" array). This is my script:
x,y,z = np.mgrid[1:10,3:18,0:5]
data = np.random.normal(0,10,[x.shape[0]-1,x.shape[1]-1,x.shape[2]-1])
visiblebox = np.random.choice([True,False],data.shape)
ax = plt.figure().add_subplot(111,projection ='3d')
colors = plt.cm.plasma(data)
ax.voxels(x,y,z,visiblebox,facecolors=colors,alpha = 0.5,edgecolor='k')
plt.colorbar(colors)
plt.show()
i have try this:
fig = plt.figure()
ax = fig.add_subplot(111,projection ='3d')
p = ax.voxels(x,y,z,visiblebox,facecolors=colors,alpha = 0.5,edgecolor='k')
fig.colorbar(p)
But I get error. I am not sure how to get colorbar to work.
Colorbar for matplotlib plot_surface using facecolorsWhen I looked up SO, I found this answer. I'm not sure about the color bar, but I fixed it while looking at the answer and the color bar showed up.
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.colors
x,y,z = np.mgrid[1:10,3:18,0:5]
data = np.random.normal(0,10,[x.shape[0]-1,x.shape[1]-1,x.shape[2]-1])
visiblebox = np.random.choice([True,False],data.shape)
ax = plt.figure().add_subplot(111,projection ='3d')
colors = plt.cm.plasma(data)
norm = matplotlib.colors.Normalize(vmin=0, vmax=16)
vox = ax.voxels(x,y,z,visiblebox,facecolors=colors,alpha = 0.5,edgecolor='k')
m = cm.ScalarMappable(cmap=plt.cm.plasma, norm=norm)
m.set_array([])
plt.colorbar(m)
plt.show()
Related
My heatmap does not change size when changing the figsize parameters. I use Latex style for my plots and have set general parameters for the plots:
# Ploting:
import matplotlib
from matplotlib import rc
import matplotlib.pyplot as plt
%matplotlib inline
rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble'] = [r'\usepackage{amsmath}']
plt.style.reload_library()
plt.style.use('science')
matplotlib.rcParams['figure.figsize'] = (7.39, 4.567)
matplotlib.rcParams['lines.linewidth'] = 0.5
matplotlib.rcParams["legend.frameon"] = True # When you need legend background color
matplotlib.rcParams['patch.linewidth'] = 0.2
matplotlib.rcParams['axes.grid'] = True
matplotlib.rcParams['grid.color'] = '#b5b5b5'
matplotlib.rcParams['grid.linestyle'] = '-'
matplotlib.rcParams['grid.linewidth'] = 0.2
Here is the code for the actual heatmap:
fig, ax = plt.subplots(figsize = (16,5))
im = ax.imshow(Granger, cmap=cmap, interpolation='none', norm=norm)
cbar = fig.colorbar(im, extend='max')
cbar.cmap.set_over('green')
fig.axes[1].set_visible(False)
# We want to show all ticks...
ax.set_xticks(np.arange(len(Granger_colnames)))
ax.set_yticks(np.arange(len(Granger_rownames)))
# ... and label them with the respective list entries
ax.set_xticklabels(Granger_colnames)
ax.set_yticklabels(Granger_rownames)
#plt.show()
plt.savefig("/content/drive/MyDrive/Plots/Granger.pdf")
I want to space out the rows and columns so that the text is better visible.
I am having trouble understanding why a custom cmap is not being properly mapped to an image using plt.imshow.
When I plot the 2-D array resr without specifying a cmap, I see:
resr = np.array([[0,2],[3,4]],dtype=int)
plt.imshow(resr)
This looks right. When I try and pass a cmap of my specified colors using:
cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f']
cmap = colors.ListedColormap(cmap1)
plt.imshow(resr, cmap=cmap)
I see:
For some reason, the color cmap1[3] is being mapped to the resr values 3 and 4. Why is this happening?
I see two options here:
A. Map data to categories
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
from mpl_toolkits.axes_grid1 import make_axes_locatable
resr = np.array([[0,2],[3,4]],dtype=int)
u, ind = np.unique(resr, return_inverse=True)
norm = colors.BoundaryNorm(np.arange(len(u)+1)-.5, len(u))
cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f']
cmap = colors.ListedColormap(cmap1)
fig,ax = plt.subplots()
im = ax.imshow(ind.reshape(resr.shape), cmap=cmap,norm=norm)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%")
cb = plt.colorbar(im, cmap=cmap,norm=norm,cax=cax)
cb.set_ticks(np.arange(len(u)))
cb.ax.set_yticklabels(cmap1)
cb.ax.tick_params(labelsize=10)
plt.show()
B. Map categories to data
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
from mpl_toolkits.axes_grid1 import make_axes_locatable
resr = np.array([[0,2],[3,4]],dtype=int)
u = np.unique(resr)
bounds = np.concatenate(([resr.min()-1], u[:-1]+np.diff(u)/2. ,[resr.max()+1]))
print(bounds)
norm = colors.BoundaryNorm(bounds, len(bounds)-1)
cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f']
cmap = colors.ListedColormap(cmap1)
fig,ax = plt.subplots()
im = ax.imshow(resr, cmap=cmap,norm=norm)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%")
cb = plt.colorbar(im, cmap=cmap,norm=norm,cax=cax)
cb.set_ticks(bounds[:-1]+np.diff(bounds)/2.)
cb.ax.set_yticklabels(cmap1)
cb.ax.tick_params(labelsize=10)
plt.show()
The result is the same for both cases.
Following #ImportanceOfBeingErnest's comment providing a link to their post, I was able to find a solution.
The trick was to use pass np.unique(resr) to BoundaryNorm. Something like:
resr = np.array([[0,2],[3,4]],dtype=int)
norm = colors.BoundaryNorm(np.unique(resr), len(np.unique(resr))-1)
cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f']
cmap = colors.ListedColormap(cmap1)
plt.imshow(resr, cmap=cmap,norm=norm);plt.colorbar()
Which returns the expected result:
I'm trying to make a bar plot with a color bar, each bar's hight is one variable (y) and each bar should have a color depending on another variable (c).
What I've got to is this (simple example):
data_x = [0,1,2,3]
data_hight = [60,60,80,100]
data_color = [1000,500,1000,900]
data_color = [x / max(data_color) for x in data_color]
fig, ax = plt.subplots(figsize=(15, 4))
my_cmap = plt.cm.get_cmap('GnBu')
colors = my_cmap(data_color)
rects = ax.bar(data_x, data_hight, color=colors)
CS = plt.contourf([data_x, data_color],cmap=my_cmap)
cbar = plt.colorbar(CS, cmap=my_cmap)
cbar.set_label('Color', rotation=270,labelpad=25)
plt.xticks(data_x)
plt.ylabel("Y")
plt.show()
The main problem is that the histogram colors are fine but the color bar is in a diferent scale. besides that I can see a blue line at y=0, it shouldn't be there.
Any help will be a preciated.
Thanks!
You are creating a contourf plot inside your bar plot. That makes no sense.
Instead you would need to create a mappable without any visual representation to supply to the colorbar. This would be a ScalarMappable.
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
data_x = [0,1,2,3]
data_hight = [60,60,80,100]
data_color = [1000.,500.,1000.,900.]
data_color = [x / max(data_color) for x in data_color]
fig, ax = plt.subplots(figsize=(15, 4))
my_cmap = plt.cm.get_cmap('GnBu')
colors = my_cmap(data_color)
rects = ax.bar(data_x, data_hight, color=colors)
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(0,max(data_color)))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Color', rotation=270,labelpad=25)
plt.xticks(data_x)
plt.ylabel("Y")
plt.show()
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 got a small problem with the positioning of a colorbar using matplotlib. I'm plotting several subplots and one of them is an image. I want this image to have a colorbar but I want it to be "stuck" to the figure, so that there is no space between the two axes (the one from the figure and the one from the colorbar). Even if the figure is resized, the colorbar should always stick to the image axes.
PS - I don't mind if ax3 (the axes of my image) is deformed.
Here's what I've got for the moment:
# Imports
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from scipy import *
# Generating data
data = (rand(2048,2048), rand(2048,2048)+1000)
colorplot = "blue"
metadata = ("Test1", "Test2", "spectral")
# Generating figure and subplots
fig = plt.figure()
fig.subplots_adjust(right = 0.8)
gs1 = gridspec.GridSpec(3, 5)
gs1.update(left=0.05,\
right=0.95,\
top=0.95,\
bottom=0.05,\
wspace=0.2,\
hspace=0.05)
ax1 = fig.add_subplot(gs1[0,0])
ax2 = fig.add_subplot(gs1[0,1])
ax3 = fig.add_subplot(gs1[1:3,0:2])
ax4 = fig.add_subplot(gs1[:,2:])
list_axes = [ax1, ax2, ax3, ax4]
for i in list_axes:
i.autoscale_view(tight=False, scalex=False, scaley=True)
# Misc computation
array = data[1]-data[0]
mean_value = np.mean(array)
std_value = np.std(array)
nb_sigma = 5
ax1.imshow(data[0], interpolation = "nearest", cmap = metadata[2])
ax2.imshow(data[1], interpolation = "nearest", cmap = metadata[2])
im = ax3.imshow(array, vmin = np.min(array[array>mean_value-nb_sigma*std_value]), vmax = np.max(array[array<mean_value+nb_sigma*std_value]), interpolation = "nearest", cmap = metadata[2])
ax3.set_adjustable('box-forced')
# Creating axes for the colorbar
axes_cb = fig.add_axes([ax3.get_position().bounds[0],ax3.get_position().bounds[1], ax3.get_position().bounds[2], 0.05])
fig.colorbar(im, cax = axes_cb, orientation = 'horizontal')
axes_cb.yaxis.tick_left()
n, bins, patches = ax4.hist(array.flatten(), color = colorplot, bins = 50, normed = True)
plt.show()
Thank you!