I am trying to automatically give each Patch
in a PatchCollection
a color from a color map like tab20
.
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(5,5))
coords = [
(0, 0),
(1, 2),
(1, 3),
(2, 2),
]
patches = [plt.Circle(coords[i], 0.1) for i in range(len(coords))]
patch_collection = PatchCollection(patches, cmap='tab20', match_original=True)
ax.add_collection(patch_collection)
ax.set_xlim(-1, 3)
ax.set_ylim(-1, 4)
plt.axis('equal')
But the above code is drawing each circle using the same color. How can the colors be cycled?
CodePudding user response:
Here I've sampled the tab20
colormap, so that the RGBA array cmap.colors
has exactly 20 different entries, then I;ve assigned this RGBA array to the keyword argument facecolors
that every collection accepts.
Not just for cosmetics, I've added a colormap, so that it's possible to recognize the order in which the circles were drawn.
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
from numpy.random import rand, seed
seed(20230104)
N = 20
coords = rand(N,2)*[2,1.2]
cmap = plt.get_cmap('tab20', N)
fig, ax = plt.subplots()
patches = [plt.Circle(coord, 0.06) for coord in coords]
# use facecolors=...
collection = PatchCollection(patches, facecolors=cmap.colors[:N-1])
ax.add_collection(collection)
cb = plt.colorbar(plt.cm.ScalarMappable(plt.Normalize(-0.5, N-0.5), cmap))
cb.set_ticks(range(N), labels=('d'%(n 1) for n in range(N)))
ax.autoscale(collection)
ax.set_aspect(1)
CodePudding user response:
This gives each patch its color from a fixed subset of colors in the selected colormap, repeating as necessary:
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
num_col = 3
cmap = plt.cm.tab20
fig, ax = plt.subplots(figsize=(5,5))
coords = [
(0, 0),
(1, 2),
(1, 3),
(2, 2),
]
patches = [plt.Circle(coords[i], 0.1) for i in range(len(coords))]
patch_collection = PatchCollection(patches, facecolor=cmap.colors[0:num_col])
ax.add_collection(patch_collection)
ax.set_xlim(-1, 3)
ax.set_ylim(-1, 4)
plt.axis('equal')
Output:
This gives a random color from the selected colormap by using numpy to generate a list of random numbers, then using the patch objects set_array
method:
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(5,5))
coords = [
(0, 0),
(1, 2),
(1, 3),
(2, 2),
]
patches = [plt.Circle(coords[i], 0.1) for i in range(len(coords))]
color_vals = np.random.rand(len(patches))
patch_collection = PatchCollection(patches, cmap='tab20', match_original=True)
patch_collection.set_array(color_vals)
ax.add_collection(patch_collection)
ax.set_xlim(-1, 3)
ax.set_ylim(-1, 4)
plt.axis('equal')
Output:
I don't think match_original=True
is necessary as you want to change the default color of the original patches. I'm sure there other ways of doing this as well. This SO post was helpful: setting color range in matplotlib patchcollection