Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
DOC: selecting individual colors from a colormap#27678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
n_lines = 21 | ||
cmap = mpl.colormaps.get_cmap('plasma').resampled(n_lines) | ||
colors = cmap.colors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I note that thecolors
attribute does not appear in the API docs. So perhaps I am not supposed to use it and should docmap(i)
instead? I find the attribute quite intuitive though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This seems a bit confusing to me. Colors won't work at all on linear segmented colormaps, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ah OK, better go back tocmap(i)
then.
# - `matplotlib.colormaps.get_cmap` | ||
# - `matplotlib.colors.Colormap` | ||
# - `matplotlib.colors.Colormap.resampled` | ||
# - `maplotlib.rc_context` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
In my local build,get_cmap
andrc_context
failed to make a link and I have no idea why.
Once we have hold of a `.Colormap` instance, the individual colors can be accessed | ||
simply using its ``.colors`` attribute. If we want a specific number of colors taken | ||
at regular intervals from a continuous colormap, we can create a new colormap using the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I found this a little confusing because you don't use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Don't use what?resampled
is used on line 22.
n_lines = 21 | ||
cmap = mpl.colormaps.get_cmap('plasma').resampled(n_lines) | ||
colors = cmap.colors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This seems a bit confusing to me. Colors won't work at all on linear segmented colormaps, right?
7dbb453
tod39e083
CompareThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This seems useful. I think it would benefit from linking tocolormap-manipulation
which I think is where we explain the different colormaps in enough detail.
I wonder if you need to caveatn_lines
with the fact that colors will get repeated forListedColormaps
ifn_lines
is larger than the lookup table? Maybe more detail than needed here
d39e083
to3140966
Compare
I did not know that. I think it might fit better in the newly linked |
# Alternatively, we may want to replace the default color cycle with a different | ||
# discrete set of colors. We can use a `~cycler.cycler` instance within `.rcParams` to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sorry to dribble comments, but I found "Alternatively" poor guidance here, as I immediately thought it would be "alternative" was of getting the colors, whereas its an alternative way of passing the colors toplot
.
Maybe something like:
# Alternatively, we may want to replace the default color cycle with a different | |
# discrete set of colors. We can use a `~cycler.cycler` instance within `.rcParams` to | |
# Instead of specifying the colors one by one in ``plot``, we can create a temporary `~cycler.cycler` that has the list of colors specified. |
3140966
to2dbd0f1
CompareThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
One small clarification. I find the integer indexing surprising for colormaps, because you need to know cmap.N (or resample) before you can use the integers. But you can take or leave the clarification, and self merge when you think ready.
Uh oh!
There was an error while loading.Please reload this page.
2dbd0f1
to95dbab0
Compare@meeseeksdev backport to v3.8.2-doc |
…678-on-v3.8.2-docBackport PR#27678 on branch v3.8.2-doc (DOC: selecting individual colors from a colormap)
…678-on-v3.8.xBackport PR#27678 on branch v3.8.x (DOC: selecting individual colors from a colormap)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@rcomer Thanks for creating the example! And sorry for being late to the party.
I've addedsome comments that you may or may not want to consider, even though the PR is already merged.
cmap = mpl.colormaps.get_cmap('plasma').resampled(n_lines) | ||
fig, ax = plt.subplots(layout='constrained') | ||
for i in range(n_lines): | ||
ax.plot([0, i], color=cmap(i)) | ||
plt.show() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would have used
colors = mpl.colormaps['plasma'](np.linspace(0, 1, n_lines))for i, color in enumerate(colors): ax.plot([0, i], color=color)
in particular
mpl.colormaps.get_cmap('plasma')
is somewhat unconventional. The ColormapRegistry supports item access for colormap names. That feels more natural to me for just looking up a colormap on the registry.get_cmap()
is similar but has additional functionality like Colormap-passthrough and default-lookup forNone
. I would either usempl.colormaps['plasma']
or just use the pyplot functionplt.get_cmap('plasma')
to save theimport mpl
(technically you could also doplt.colormaps['plasma']
because we re-export the registry in pyplot).- I didn't even know that one can index colormaps by integer, and I find it a bit harder to understand. First, one has to know the integer-indexing (which feels half an implementation detail to me because I regard the colormaps as conceptually continuous). Second, looking up the color is now split beween creating the resampled
cmap
(l.24) and later looking up the color (l.29). They only make sense together but are quite separted. The vectorized approach of mapping an array of floats to colors is more explicit. Note also that you can easily sample parts of the colormap in the vectorized lookup, e.g.mpl.colormaps['RdYlGn'](np.linspace(0.5, 1, n_lines))
to sample only the upper half of a diverging colormap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
cmap = mpl.colormaps.get_cmap('Dark2') | ||
colors = cmap(range(cmap.N)) # cmap.N is number of unique colors in the colormap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The qualitative colormaps areListedColormap
s and obtaining all their colors can be done easier via:
colors = mpl.colormaps['Dark2'].colors
Note that this is a significantly different task than selecting N equidistant colors from a continuous map. I'm not clear on the focus we want to set here:#27671 was primaily "I have N lines and want differnt colors", which is the first part here. Mycomment on a context example was the idea one should mention in the context of the above task that you can make a context so that you don't have to carry the colors explicitly. That's a different direction than focussing on various aspects of getting color values. Both ways are possbile, but we should not mix them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hmmm, I started by using thecolors
attribute for both examples (plasma is also aListedColorMap
), but changed it in response to one of@jklymak’s comments.
My thinking for using a qualitative colormap: if someone is changing the color cycle in rcParams then they are using it across several plots which might need different numbers of colors, so getting a specific number of colors out of a continuous map would make less sense there. This is in the context where the user was also asking for an increase in the default cycle.
rcomer commentedJan 22, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@timhoffm apologies, I should have waited to give you a chance to comment before merging since you had put ideas in the issue. |
@rcomer Better to keep things moving in this case than to let it fall off everyone's radar! |
PR summary
Closes#27671 by adding an example to show using colormaps in places where we need discrete sets of colours.
The plots themselves could be more interesting, but I guess the more interesting we make them the more code there will be to distract from the main point.
PR checklist