How to customize the colorbar in python? - python

Using this code, I don't know how to customize the colorbar. The colormaps on this webiste can't satisfy me.
shade = m.contourf(Lon,Lat,TBB,np.arange(-90, -20, 10),extend='both',cmap=plt.cm.get_cmap('jet'))
m.colorbar(shade)
I want to draw a picture like this with obvious colorbar. So, what should I do?

You can define your own colormap using matplotlib.colors.LinearSegmentedColormap() or matplotlib.colors.ListedColormap() and use it for your plot.
Example:
import numpy as np; np.random.seed(0)
import matplotlib.pyplot as plt
import matplotlib.colors
x = np.arange(0,25)
a = np.random.randint(0,130, size=(25,25))-115
a = np.sort(a).reshape(25,25)
colors = ["#eaa941", "#efef39", "#53a447", "#3b387f", "#48a2ba"]
cmap= matplotlib.colors.ListedColormap(colors)
cmap.set_under("crimson")
cmap.set_over("w")
norm= matplotlib.colors.Normalize(vmin=-100,vmax=-0)
fig, ax = plt.subplots()
im = ax.contourf(x,x,a, levels=[-100,-80,-60,-40,-20,0],
extend='both',cmap=cmap, norm=norm)
fig.colorbar(im, extend="both")
plt.show()

Looks a lot like the spectral colormap, which is given on the matplotlib page..

Related

How can I use the matplotlib to draw this picture?

I want to use grid to achieve this. However, I have encountered many problems with color fills and axes。I refer to an example in the official matplotlib documentation that is very close to this image
(the link), but it's still a little different.
here is the picture
It's my fault, the picture is too large,it's difficult to implement quickly. So i choose a part of the original image, here:
Try with plotting custom heatmaps. For example
from matplotlib import colors
import matplotlib.pyplot as plt
import numpy as np
cmap = colors.ListedColormap(['cyan','gray','white','yellow'])
bounds=[0, 10, 20, 30, 40]
norm = colors.BoundaryNorm(bounds, cmap.N)
data=np.array([[5,15,5],[25,32,6],[15,31,25]])
heatmap = plt.pcolor(data, cmap=cmap, norm=norm)
plt.show()
a value between 0-10 will give cyan colour, 10-20 will give gray as so on. So make your data array accodingly.
Result :
I've solved this qusetion by using seaborn.
from matplotlib import colors
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
cmap = colors.ListedColormap(['white','gray','blue','yellow'])
bounds=[0, 2, 4, 6, 8]
norm = colors.BoundaryNorm(bounds, cmap.N)
data = np.array([[1,1,1,1,7,7,7,7], [1,1,1,1,1,1,1,5], [1,1,1,1,1,1,1,5], [1,1,1,3,1,1,1,5], [1,1,1,1,1,1,3,5]])
ax = sns.heatmap(data, cmap=cmap, norm=norm, linewidths=.5,
linecolor='black', square=True, cbar=False)
sns.plt.annotate('S', (1.4, 3.4))
sns.plt.show()
result

seaborn color_palette as matplotlib colormap

Seaborn offers a function called color_palette, which allows you to easily create new color_palettes for plots.
colors = ["#67E568","#257F27","#08420D","#FFF000","#FFB62B","#E56124","#E53E30","#7F2353","#F911FF","#9F8CA6"]
color_palette = sns.color_palette(colors)
I want to transform color_palette to a cmap, which I can use in matplotlib, but I don't see how I can do this.
Sadly just functions like "cubehelix_palette","light_palette",… have an "as_cmap" paramater. "color_palette" doesn't, unfortunately.
You have to convert a list of colors from seaborn palette to color map of matplolib (thx to #RafaelLopes for proposed changes):
import seaborn as sns
import matplotlib.pylab as plt
import numpy as np
from matplotlib.colors import ListedColormap
# construct cmap
flatui = ["#9b59b6", "#3498db", "#95a5a6", "#e74c3c", "#34495e", "#2ecc71"]
my_cmap = ListedColormap(sns.color_palette(flatui).as_hex())
N = 500
data1 = np.random.randn(N)
data2 = np.random.randn(N)
colors = np.linspace(0,1,N)
plt.scatter(data1, data2, c=colors, cmap=my_cmap)
plt.colorbar()
plt.show()
Most seaborn methods to generate color palettes have an optional argument as_cmap which by default is False. You can use to directly get a Matplotlib colormap:
import seaborn as sns
import matplotlib.pylab as plt
import numpy as np
# construct cmap
my_cmap = sns.light_palette("Navy", as_cmap=True)
N = 500
data1 = np.random.randn(N)
data2 = np.random.randn(N)
colors = np.linspace(0,1,N)
plt.scatter(data1, data2, c=colors, cmap=my_cmap)
plt.colorbar()
plt.show()
The first answer is somehow correct but way too long with a lot of unnecessary information. The correct and short answer is:
To convert any sns.color_palette() to a matplotlib compatible cmap you need two lines of code
from matplotlib.colors import ListedColormap
cmap = ListedColormap(sns.color_palette())
Just an additional tip - if one wants a continuous colorbar/colormap, adding 256 as the number of colors required from Seaborn colorscheme helps a lot.
cmap = ListedColormap(sns.color_palette("Spectral",256))

How can I create a discrete colorbar using a colormap from mpl_toolkits.basemap.cm?

When I plot the pcolormesh plot use the colormap from matplotlib.cm (like "jet", "Set2", etc), I can use:
cMap = plt.cm.get_cmap("jet",lut=6)
The colorbar shows like this:
But if I want to call the colormap from the Basemap package (like GMT_drywet, GMT_no_green, etc). I can't use plt.cm,get_cmap to get these colormap and divide them.
Does mpl_toolkits.basemap.cm have a similiar function like lut?
Expanding on #tacaswell's comment above, you can achieve the same functionality using the _resample method. This will produce segmented colormaps for pcolor/pcolormesh plots which don't generate discrete-stepped colorbars like contourf. To achieve the same effect as you did with jet in your question:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import cm
plt.figure()
cmap = cm.GMT_drywet._resample(6)
pm = plt.pcolormesh(np.random.rand(10,8), cmap=cmap)
plt.colorbar(pm, orientation='horizontal')
plt.show()
As long as the plot you are making has discrete color values (e.g. contour or contourf), then colorbar should automatically generate a colorbar with discrete steps. Here's a plot based on the first example from the basemap documentation:
from mpl_toolkits.basemap import Basemap, cm
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1, 1)
ax.hold(True)
map = Basemap(projection='ortho',lat_0=45,lon_0=-100,resolution='l')
map.drawcoastlines(linewidth=0.25)
map.drawcountries(linewidth=0.25)
map.fillcontinents(color='coral',lake_color='aqua')
map.drawmapboundary(fill_color='aqua')
map.drawmeridians(np.arange(0,360,30))
map.drawparallels(np.arange(-90,90,30))
nlats = 73; nlons = 145; delta = 2.*np.pi/(nlons-1)
lats = (0.5*np.pi-delta*np.indices((nlats,nlons))[0,:,:])
lons = (delta*np.indices((nlats,nlons))[1,:,:])
wave = 0.75*(np.sin(2.*lats)**8*np.cos(4.*lons))
mean = 0.5*np.cos(2.*lats)*((np.sin(2.*lats))**2 + 2.)
x, y = map(lons*180./np.pi, lats*180./np.pi)
map.contourf(x,y,wave+mean,15, alpha=0.5, cmap=cm.GMT_drywet)
cb = map.colorbar()
plt.show()

How do I add a colorbar with log data in an image/matrix

I have a 2D matrix I want to plot. The plotting itself works, but I need
a colorbar with it. The figure only makes sense when the data is
log-tranformed. And I want the colorbar show the original values. How
do I do this?
A search provided
A logarithmic colorbar in matplotlib scatter plot
but I cannot make this work.
The code below gives an idea of what I attempt to do. Only the revevant
lines are included (as far as I could see).
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
my_speed=np.ones(shape=(no,no))
fig=plt.figure(2)
ax=fig.add_subplot(1,1,1)
my_speed=np.log10(my_speed)
ax.imshow(my_speed, interpolation='bilinear', cmap=cm.jet)
plt.colorbar() #this does not work
plt.savefig('myspeedplot.png')
plt.close(2)
Thank you for any help
The idea is not to transform your data, but let the visualization do the trick for you.
pylot.imshow[1] has an optional parameter norm that can do the log transformation for you.
my_speed=np.ones(shape=(no,no))
fig = plt.figure(2)
ax = fig.add_subplot(1,1,1)
# my_speed=np.log10(my_speed)
img = ax.imshow(my_speed, interpolation='bilinear', cmap=cm.jet,
norm=mpl.colors.LogNorm())
fig.colorbar(img)
As far as I see, there are two problems with your code.
First, you are trying to have the ticks on colorbar show original values. For this you should not transform the data, but just normalize the plot.
And second, you are using the ax.imshow and this is why the colorbar does not see it. You should use plt.imshow or use im=ax.imshow and then colorbar(im)
Here is a working solution:
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
my_speed = np.random.rand(20, 20)
fig = plt.figure(2)
ax = fig.add_subplot(1, 1, 1)
im = ax.imshow(my_speed, interpolation='bilinear',
norm=mpl.colors.LogNorm(),
cmap=plt.cm.jet)
cb = plt.colorbar(im, orientation='vertical')
plt.show()

Creating a Colormap Legend in Matplotlib

I am using imshow() in matplotlib like so:
import numpy as np
import matplotlib.pyplot as plt
mat = '''SOME MATRIX'''
plt.imshow(mat, origin="lower", cmap='gray', interpolation='nearest')
plt.show()
How do I add a legend showing the numeric value for the different shades of gray. Sadly, my googling has not uncovered an answer :(
Thank you in advance for the help.
Vince
Simple, just plt.colorbar():
import numpy as np
import matplotlib.pyplot as plt
mat = np.random.random((10,10))
plt.imshow(mat, origin="lower", cmap='gray', interpolation='nearest')
plt.colorbar()
plt.show()
There's a builtin colorbar() function in pyplot. Here's an example using subplots:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plot = ax.pcolor(data)
fig.colorbar(plot)
As usual, I figure it out right after I ask it ;). For posterity, here's my stab at it:
m = np.zeros((1,20))
for i in range(20):
m[0,i] = (i*5)/100.0
print m
plt.imshow(m, cmap='gray', aspect=2)
plt.yticks(np.arange(0))
plt.xticks(np.arange(0,25,5), [0,25,50,75,100])
plt.show()
I'm sure there exists a more elegant solution.
Vince

Categories

Resources