Setting Matplotlib Colorbar Range

Set Colorbar Range in matplotlib

Using vmin and vmax forces the range for the colors. Here's an example:

enter image description here

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
'red' : ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
'green': ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
'blue' : ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )

def do_plot(n, f, title):
#plt.clf()
plt.subplot(1, 3, n)
plt.pcolor(X, Y, f(data), cmap=cm, vmin=-4, vmax=4)
plt.title(title)
plt.colorbar()

plt.figure()
do_plot(1, lambda x:x, "all")
do_plot(2, lambda x:np.clip(x, -4, 0), "<0")
do_plot(3, lambda x:np.clip(x, 0, 4), ">0")
plt.show()

set colorbar range with contourf

contourf indeed works a bit differently than other ScalarMappables. If you specify the number of levels (20 in this case) it will take them between the minimum and maximum data (approximately). If you want to have n levels between two specific values vmin and vmax you would need to supply those to the contouring function

levels = np.linspace(vmin, vmax, n+1)
plt.contourf(fld,levels=levels,cmap='coolwarm')

Complete code:

import numpy as np
import matplotlib.pyplot as plt
fld=np.random.rand(10,10)
levels = np.linspace(0,2,21)
img=plt.contourf(fld,levels=levels,cmap='coolwarm')
plt.colorbar(img)
plt.show()

enter image description here

matplotlib colorbar limits for contourf

You could pass levels parameter to matplotlib.pyplot.contourf in order to specify the number and positions of the contour regions. Then you can set extend = 'both' in order to draw the countour regions outside levels range you used:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()

ax = fig.gca(projection='3d')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 10*2*M*np.sin( 2 * np.deg2rad(CHI) )

levels = [-3, -2, -1, 0, 1, 2, 3]

cont = ax.contourf(CHI, M, R, levels = levels, extend = 'both')

ax.set_xlim(-45,45)
cbar = plt.colorbar(cont)
plt.show()

Sample Image

how to instantly update the colorbar range of a matplotlib from values of entries?

So what You want in the end is to change colormap vmin and vmax, when user change Min and Max input. You don't need to constantly update colormap, but just on change of those inputs.

You can do that by tracing input change with update callback.

Here is modified code which does colormap update when Min and Max input is changed:

from tkinter import *

import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

root = Tk()
root.geometry("500x500")

Max, Min = IntVar(), IntVar()

label1 = Label(root, text="Min")
label1.place(x=10, y=35)

label2 = Label(root, text="Max")
label2.place(x=10, y=60)

vmin_entry = Entry(root, textvariable=Min, width=5)
vmin_entry.place(x=50, y=35)

vmax_entry = Entry(root, textvariable=Max, width=5)
vmax_entry.place(x=50, y=60)

# Define global variables
c, canvas = None, None

def plot():
global x, y, c, canvas
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x * y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)

c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)

canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
canvas.draw()


def update_colormap(*args, **kwargs):
global c, canvas
if c is not None:
try:
# Get vmin and vmax
vmin, vmax = int(vmin_entry.get()), int(vmax_entry.get())
except ValueError:
# Could not convert values to int, non integer value
return
if vmin > vmax:
return
# Set new limits
c.set_clim(vmin, vmax)
# Update plot
canvas.flush_events()
canvas.draw()


# Trace change of Min and Max and call update_colormap as a callabck
Min.trace("w", update_colormap)
Max.trace("w", update_colormap)

button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)

root.mainloop()

Setting matplotlib colorbar range (larger range than the values plotted)

I finally managed to solve it.
Instead of vmin and vmax, I must pass a keyword to control the levels to draw, like this:

import matplotlib.pyplot as plt
import numpy as np

rd = np.random.rand(40,100)
surface = 18 * rd # maximum value will be 18

fig = plt.figure()
ax = fig.add_subplot(111)

cores = ax.contourf(surface[:], levels=range(41))
cbar = plt.colorbar(cores)

plt.show()

And I get the image I wanted:
enter image description here

Setting matplotlib colorbar range

Arg. It's always the last thing you try:

quadmesh.set_clim(vmin=0, vmax=15)

works.

Set Colorbar range with contourf in matplotlib

The following always produces a bar with colours that correspond to the colours in the graph, but shows no colours for values outside of the [vmin,vmax] range.

It can be edited (see inline comment) to give you exactly the result you want, but that the colours of the bar then still correspond to the colours in the graph, is only due to the specific colour map that's used (I think):

# Start copied from your attempt
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(20)
y = np.arange(20)
data = x[:, None] + y[None, :]

X, Y = np.meshgrid(x, y)
vmin = 0
vmax = 15


fig, ax = plt.subplots()

# Start of solution
from matplotlib.cm import ScalarMappable
levels = 400

level_boundaries = np.linspace(vmin, vmax, levels + 1)

quadcontourset = ax.contourf(
X, Y, data,
level_boundaries, # change this to `levels` to get the result that you want
vmin=vmin, vmax=vmax
)


fig.colorbar(
ScalarMappable(norm=quadcontourset.norm, cmap=quadcontourset.cmap),
ticks=range(vmin, vmax+5, 5),
boundaries=level_boundaries,
values=(level_boundaries[:-1] + level_boundaries[1:]) / 2,
)

Always correct solution that can't handle values outside [vmin,vmax]:
always correct solution that can't handle values outside [vmin,vmax]

Requested solution:
requested solution



Related Topics



Leave a reply



Submit