Is there a way to change the transition values of a continuous colormap (cmap) in matplotlib? I want to use "vlag" to color a heatmap, however my values only typically range from 0 to 0.6 (instead of 0-1). I could renormalize my data or use vmin & vmax, however I was curious if there was a way to set transition points for vlag between 0-1. There are three colors in vlag (blue, white, and red). Having set transition points will allow for an apples to apples comparison between different heatmaps.
If the colormap only contains few colors, a BoundaryNorm lets you specify the transition points.
For a colormap with a smooth range of colors, a TwoSlopeNorm lets you move the spots where the transitions start happening.
from matplotlib.colors import TwoSlopeNorm
import seaborn as sns # for the 'vlag' colormap
import numpy as np
x = np.linspace(0, 10, 200)
y = np.sin(x)**2
fig, axs = plt.subplots(ncols=2, figsize=(12, 4))
scat0 = axs[0].scatter(x, y, c=y, cmap='vlag')
axs[0].set_title('default norm')
plt.colorbar(scat0, ax=axs[0])
norm = TwoSlopeNorm(vmin=0., vcenter=0.3, vmax=1)
scat1 = axs[1].scatter(x, y, c=y, cmap='vlag', norm=norm)
axs[1].set_title('TwoSlopeNorm')
plt.colorbar(scat1, ax=axs[1])
plt.tight_layout()
plt.show()
Related
I have two datasets (corresponding with the time-positional data of hydrogen atoms and time-positional data of alumina atoms) in the same system.
I want to plot the density of each element by overlaying two hist2d plots using matplotlib.
I am currently doing this by setting an alpha value on the second hist2d:
fig, ax = plt.subplots(figsize=(4, 4))
v = ax.hist2d(x=alx, y=aly,
bins=50, cmap='Reds')
h = ax.hist2d(x=hx, y=hy,
bins=50, cmap='Blues',
alpha=0.7)
ax.set_title('Adsorption over time, {} K'.format(temp))
ax.set_xlabel('picoseconds')
ax.set_ylabel('z-axis')
fig.colorbar(h[3], ax=ax)
fig.savefig(savename, dpi=300)
I do get the plot that I want, however the colors seem washed out due to the alpha value.
Is there a more correct way to do generate such plots?
One way to achieve this would be a to add fading alphas towards lower levels to the existing color maps:
import numpy as np
import matplotlib.pylab as pl
from matplotlib import pyplot as plt
from matplotlib.colors import ListedColormap
# modify existing Reds colormap with a linearly fading alpha
red = pl.cm.Reds # original colormap
fading_red = red(np.arange(red.N)) # extract colors
fading_red[:, -1] = np.linspace(0, 1, red.N) # modify alpha
fading_red = ListedColormap(fading_red) # convert to colormap
# data generation
random_1 = np.random.randn(10000)+1
random_2 = np.random.randn(10000)+1
random_3 = np.random.randn(10000)
random_4 = np.random.randn(10000)
# plot
fig, ax = plt.subplots(1,1)
plt.hist2d(x=random_3, y=random_4, bins=100, cmap="Blues")
plt.hist2d(x=random_1, y=random_2, bins=50, cmap=fading_red)
plt.show()
I find matplotlib to be one of the mot confusing libraries to figure out :(
I am using the scatter function of an axis to plot some points, and each point has its own weight associated with it that controls the opacity...
colors = [(*c[:3], w.item() / 1) for w in weight]
ax.scatter(gen, samples, c=colors, s=10, marker="*", label="$\\tilde{x}$", zorder=-100)
ax.legend
The problem is that the color in the legend appears to be a random color from the colors array. Sometimes it is translucent because some of the colors in the scatter are nearly translucent. I would like the color in the legend to be solid, while keeping the variable colors in the scatterplot.
How would I accomplish this?
Changing only the alpha value of the legend handle turned out to be more difficult than expected (the obvious way item.set_alpha(1) creates problems with some of the colors that will be nearly invisible). But you can set the handle color, giving the legend a uniform appearance:
from matplotlib import pyplot as plt
#fake data generation
import numpy as np
n = 10
np.random.seed(1234)
gen = np.random.randint(1, 10, n)
samples = np.random.randint(10, 50, n)
colors = np.random.rand(n, 4)
#reduce the alpha values for demonstration purposes
colors[:, 3] = colors[:, 3]/3
fig, ax = plt.subplots(figsize=(10,8))
ax.scatter(gen, samples, c=colors, s=70, marker="o", label="$\\tilde{y}$", zorder=-100)
ax.scatter(samples, gen, c=colors, s=50, marker="x", label="$\\tilde{x}$", zorder=-100)
l = ax.legend()
for item in l.legendHandles:
item.set_color("black")
plt.show()
Sample output:
Values in my matrix called 'energy' are close enough to each other: e.g. one value can be 500, another one 520. And i want to see the color difference on my plot more precisely. Like for the smallest value in my data it should be the very dark color and for the highest value it should be the very bright color.
I have the following code:
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111)
plt.imshow(energy[0:60, 0:5920], cmap='Reds')
ax.axes.set_aspect(aspect=100)
plt.grid(color='yellow')
plt.title('My plot')
plt.xlabel('Length points')
plt.ylabel('Time points(seconds)')
import matplotlib.ticker as plticker
loc = plticker.MultipleLocator(base=500)
ax.xaxis.set_major_locator(loc)
plt.show()
I get the following plot:
plot of energy
Other words i'd love to get this plot more colorful.
Thanks in advance.
You can set a custom range either through a custom colormap or adjusting the range value to show using the keywords vmin and vmax. For example:
from matplotlib.pyplot import subplots
import numpy as np
fig, ax = subplots()
h = ax.imshow(np.random.rand(10,10) * 10, vmin = 0,\
vmax = 2, cmap = 'Reds')
fig.colorbar(h)
fig.show()
Which produces the colors within 0, 2 value
Alternatively you can rescale your data or adjust your colormap, see the maplotlib docs for more info.
I have two lists containing the x and y coordinates of some points. There is also a list with some values assigned to each of those points. Now my question is, I can always plot the points (x,y) using markers in python. Also I can select colour of the marker manually (as in this code).
import matplotlib.pyplot as plt
x=[0,0,1,1,2,2,3,3]
y=[-1,3,2,-2,0,2,3,1]
colour=['blue','green','red','orange','cyan','black','pink','magenta']
values=[2,6,10,8,0,9,3,6]
for i in range(len(x)):
plt.plot(x[i], y[i], linestyle='none', color=colour[i], marker='o')
plt.axis([-1,4,-3,4])
plt.show()
But is it possible to choose a colour for the marker marking a particular point according to the value assigned to that point (using cm.jet, cm.gray or similar other color schemes) and provide a colorbar with the plot ?
For example, this is the kind of plot I am looking for
where the red dots denote high temperature points and the blue dots denote low temperature ones and others are for temperatures in between.
You are most likely looking for matplotlib.pyplot.scatter. Example:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# Generate data:
N = 10
x = np.linspace(0, 1, N)
y = np.linspace(0, 1, N)
x, y = np.meshgrid(x, y)
colors = np.random.rand(N, N) # colors for each x,y
# Plot
circle_size = 200
cmap = matplotlib.cm.viridis # replace with your favourite colormap
fig, ax = plt.subplots(figsize=(4, 4))
s = ax.scatter(x, y, s=circle_size, c=colors, cmap=cmap)
# Prettify
ax.axis("tight")
fig.colorbar(s)
plt.show()
Note: viridis may fail on older version of matplotlib.
Resulting image:
Edit
scatter does not require your input data to be 2-D, here are 4 alternatives that generate the same image:
import matplotlib
import matplotlib.pyplot as plt
x = [0,0,1,1,2,2,3,3]
y = [-1,3,2,-2,0,2,3,1]
values = [2,6,10,8,0,9,3,6]
# Let the colormap extend between:
vmin = min(values)
vmax = max(values)
cmap = matplotlib.cm.viridis
norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
fig, ax = plt.subplots(4, sharex=True, sharey=True)
# Alternative 1: using plot:
for i in range(len(x)):
color = cmap(norm(values[i]))
ax[0].plot(x[i], y[i], linestyle='none', color=color, marker='o')
# Alternative 2: using scatter without specifying norm
ax[1].scatter(x, y, c=values, cmap=cmap)
# Alternative 3: using scatter with normalized values:
ax[2].scatter(x, y, c=cmap(norm(values)))
# Alternative 4: using scatter with vmin, vmax and cmap keyword-arguments
ax[3].scatter(x, y, c=values, vmin=vmin, vmax=vmax, cmap=cmap)
plt.show()
I am using matplotlib to make some plots and I have run into a few difficulties that I need help with.
problem 1) In order to keep a consistent colorscheme I need to only use half of the color axis. There are only positive values, so I want the zero values to be green, the mid values to be yellow and the highest values to be red. The color scheme that most closely matches this is gist_rainbow_r, but I only want the top half of it.
problem 2) I can't seem to figure out how to get the colorbar on the right hand side of the plot to show up or how to get it to let me label the axes.
If it helps, I am using the latest version of Anaconda wth the latext version of matplotlib
cmap = plt.get_cmap('gist_rainbow_r')
edosfig2 = plt.figure(2)
edossub2 = edosfig.add_subplot(1,1,1)
edossub2 = plt.contourf(eVec,kints,smallEDOS,cmap=cmap)
edosfig2.show()
If you have a specific set of colors that you want to use for you colormap, you can build it based on those. For example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
cmap = LinearSegmentedColormap.from_list('name', ['green', 'yellow', 'red'])
# Generate some data similar to yours
y, x = np.mgrid[-200:1900, -300:2000]
z = np.cos(np.hypot(x, y) / 100) + 1
fig, ax = plt.subplots()
cax = ax.contourf(x, y, z, cmap=cmap)
cbar = fig.colorbar(cax)
cbar.set_label('Z-Values')
plt.show()
However, if you did just want the top half of some particularly complex colormap, you can copy a portion of it by evaluating the colormap over the range you're interested in. For example, if you wanted the "top" half, you'd evaluate it from 0.5 to 1:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# Evaluate an existing colormap from 0.5 (midpoint) to 1 (upper end)
cmap = plt.get_cmap('gist_earth')
colors = cmap(np.linspace(0.5, 1, cmap.N // 2))
# Create a new colormap from those colors
cmap2 = LinearSegmentedColormap.from_list('Upper Half', colors)
y, x = np.mgrid[-200:1900, -300:2000]
z = np.cos(np.hypot(x, y) / 100) + 1
fig, axes = plt.subplots(ncols=2)
for ax, cmap in zip(axes.flat, [cmap, cmap2]):
cax = ax.imshow(z, cmap=cmap, origin='lower',
extent=[x.min(), x.max(), y.min(), y.max()])
cbar = fig.colorbar(cax, ax=ax, orientation='horizontal')
cbar.set_label(cmap.name)
plt.show()