I want a color gradient between black and red in matplotlib, where the low values are black and become more and more red with increasing Y-value.
import matplotlib.pyplot as plt
xvals = np.arange(0, 1, 0.01)
yvals = xvals
plt.plot(xvals, yvals, "r")
axes = plt.axes()
plt.show()
What do I have to change to get such a color gradient?
From the matplotlib documentation you can check this link as an example.
To create that colormap you just need to do:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = [(0, 0, 0), (1, 0, 0)] # first color is black, last is red
cm = LinearSegmentedColormap.from_list(
"Custom", colors, N=20)
mat = np.indices((10,10))[1]
plt.imshow(mat, cmap=cm)
plt.show()
This results in this:
Related
I don't really understand the documentation on colorbar I wanted explanation on a basic example. So below I am plotting exp(-x*a) for a={1, 2, 3, 4}. How do I add color bar with the values of a.
import numpy as np
import matplotlib.pyplot as plt
def func(x,a):
return np.exp(-x*a)
x = np.linspace(0, 5)
for a in range(1,5):
plt.plot(func(x,a))
plt.show()
I'm confused with imshow, subplot, ax.
Colour schemes are defined in the range 0 to 1, therefore you first need to normalise your values (0 to 5) to the range 0 to 1. Then you can pull the colour from the colormap. At the end you have to plot a color bar using the colour map and norm that you chose on the axis you used for plotting.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm, colors
def func(x, a):
return np.exp(-x * a)
x = np.linspace(0, 5)
fig, ax = plt.subplots()
# define color map
cmap = cm.get_cmap("Spectral")
# need to normalize because color maps are defined in [0, 1]
norm = colors.Normalize(0, 5)
for a in range(1, 5):
ax.plot(x, func(x, a),
color=cmap(norm(a))) # get color from color map
# plot colorbar
fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax)
plt.show()
The plot looks like this:
I have some simple to code create a hex plot with Seaborn. I want to use the viridis color palette but I want it to be white where the density is 0. Is this possible? I would like the block of purple below to be white/not visible.
g = sns.jointplot(x =depth, y = abs(depth-med), kind="hex", joint_kws={"color":'White', 'cmap':'viridis'})
sns.set_style("whitegrid")
You can set vmin for the normalization to a value below 1 and set the clipped data points to white:
import matplotlib.pyplot as plt
from matplotlib import cm
import seaborn as sns
my_viridis = cm.get_cmap("viridis", 1024).with_extremes(under="white")
penguins = sns.load_dataset("penguins")
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", kind="hex", joint_kws={"color":'White', "camp": my_viridis, "vmin": 0.1})
plt.show()
Sample output:
Alternatively, we can change the specific value for zero of the colormap:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm, colors
import seaborn as sns
dummy = cm.get_cmap("viridis")
dummy2 = dummy(np.linspace(0, 1, 1024))
dummy2[0] = np.asarray([1, 1, 1, 1])
#or you can set zero to transparent with
#dummy2[0] = np.asarray([1, 1, 1, 0])
my_viridis = colors.ListedColormap(dummy2)
penguins = sns.load_dataset("penguins")
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", kind="hex", joint_kws={"color":'White', "cmap": my_viridis})
plt.show()
Using a simulation, I was able to construct a list of battery levels in percentage decreasing over time as you can see here :
I was already able to dispay the battery levels depending on the time using matplotlib pyplot.
This list has a size of 1944 elements and I would like to know if there is a possibility to display these battery levels depending on the time using a custom colorbar from green (100% of battery) to red (around 15% of battery) to black (below 15% of battery which is critical).
You can use a LinearSegmentedColormap.from_list() using tuples of values and colors. Here is an example using a seaborn heatmap to show how it works:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import seaborn as sns
cmap = LinearSegmentedColormap.from_list('', [(0, 'black'), (.15, 'black'), (.15, 'crimson'), (1, 'limegreen')])
fig, ax = plt.subplots(figsize=(5, 10))
sns.heatmap(np.linspace(100, 0, 30).reshape(-1, 1), annot=True, fmt='.2f', cmap=cmap, ax=ax)
PS: plt.plot() can't be used with a colormap. A curve has just one given color. You could use plt.scatter(temps_total_simulation, pourcentage_total, c=pourcentage_total, cmap=cmap, vmin=0, vmax=100) to individual points.
In matplotlib's tutorial, there is an example to split a curve into individual line segments, and then color these segments. Note that there is one segment less than there are points, as each segment connects two points. The mean of the percentage values of the endpoints of a segment could define the segment's color:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.collections import LineCollection
import numpy as np
cmap = LinearSegmentedColormap.from_list('', [(0, 'black'), (.15, 'black'), (.15, 'crimson'), (1, 'limegreen')])
fig, ax = plt.subplots(figsize=(12, 5))
temps_total_simulation = np.arange(1000)
pourcentage_total = np.random.randn(len(temps_total_simulation)).cumsum()
pourcentage_total -= pourcentage_total.min()
pourcentage_total = pourcentage_total / pourcentage_total.max() * 100
# ax.scatter(temps_total_simulation, pourcentage_total, s=3, c=pourcentage_total, cmap=cmap)
pnts = np.c_[temps_total_simulation, pourcentage_total]
segments = np.c_[pnts[:-1], pnts[1:]].reshape(-1, 2, 2)
linecol = LineCollection(segments, cmap=cmap, norm=plt.Normalize(0, 100))
linecol.set_array(
(pourcentage_total[:-1] + pourcentage_total[1:]) / 2) # use the mean percentage for colloring the segment
linecol.set_linewidth(1)
ax.add_collection(linecol)
ax.set_xlim(temps_total_simulation[0], temps_total_simulation[-1])
ax.set_ylim(0, 100)
plt.show()
Consider the following:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
plot = plt.scatter(y, y, c = y, cmap = 'hsv')
plt.clf()
plt.colorbar(plot)
plt.bar(range(len(y)), y, color = colors)
plt.show()
I want to colormap legend to appear on the top right of the graph (much smaller of course). My image at the moment looks rather clunky as the colormap is clashing somewhat with the actual bars.
Thanks.
Following this answer:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
fig, ax = plt.subplots()
plot = ax.scatter(y, y, c = y, cmap = 'hsv')
plt.cla()
ax.bar(range(len(y)), y, color = colors)
cbaxes = inset_axes(ax, width="30%", height="3%", loc=2)
plt.colorbar(plot, cax=cbaxes, orientation='horizontal', ticks=[0,2,4,6,8,10])
I use plt.subplots to easily reference the Axes (ax). You can move the color bar and change its size by editing the last 2 lines (for instance changing loc can set which corner you want the colorbar to be in).
I'm trying to plot an image with a superimposed fitted curve, but for now I'll just provide an example of an image.
I have been following this example ( http://matplotlib.org/examples/pylab_examples/colorbar_tick_labelling_demo.html ), but when I try to replace the gaussian noise with an image the color bar tick marks don't display correctly (i.e they are all smashed down at the left end).
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from matplotlib import cm
from numpy.random import randn
fig, ax = plt.subplots()
data = np.clip(randn(250, 250), -1, 1)
#data = Image.open('testTop.tif')
cax = ax.imshow(data, interpolation='nearest', cmap=cm.afmhot)
ax.set_title('colorBar fun')
cbar = fig.colorbar(cax, ticks=[-1, 0, 1], orientation='horizontal')
cbar.ax.set_xticklabels(['Low', 'Medium', 'High'])# horizontal colorbar
plt.show()
#data = np.clip(randn(250, 250), -1, 1)
data = Image.open('testTop.tif')
Is there something intrinsic about displaying images that skews the colorbar, or is there something else obvious that I'm missing?
The colorbar axis only goes from -1 to 1 in the example with the random nose because the data ranges from -1 to 1. The tif image your using probably has a different range of values. You can get the minimum and maximum values of the data you're plotting and use that to set the color bar ticks. Here's an example that will work with both the random data and an image:
import matplotlib.cbook as cbook
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from matplotlib import cm
from numpy.random import randn
# Load sample image
image_file = cbook.get_sample_data('grace_hopper.png')
data = plt.imread(image_file)
data = data[:,:,0] # Take only one channel for a grey scale image.
#data = np.clip(randn(250, 250), -1, 1)
fig, ax = plt.subplots()
cax = ax.imshow(data, interpolation='nearest', cmap=cm.afmhot)
ax.set_title('colorBar fun')
dataMin = np.amin(data)
dataMax = np.amax(data)
mid = ((dataMax - dataMin) / 2) + dataMin
cbar = fig.colorbar(cax, ticks=[dataMin, mid, dataMax], orientation='horizontal')
cbar.ax.set_xticklabels(['Low', 'Medium', 'High'])# horizontal colorbar
plt.show()