Research has shown that the rainbow color map is rarely the optimal choice when displaying data with a pseudocolor map. The rainbow color map confuses viewers through its lack of perceptual ordering, obscures data through its uncontrolled luminance variation, and actively misleads interpretation through the introduction of non-data-dependent gradients.
Despite much published research on its deficiencies the rainbow color map is prevalent in the visualization community. We present survey results showing that the rainbow color map continues to appear in more than half of the relevant papers in IEEE Visualization Conference proceedings; for example, it appeared on 61 pages in 2005. Its use is encouraged by its selection as the default color map used in most visualization toolkits that we inspected. The visualization community must do better.
...
In the absence of feedback about the data or task, the best approach for situations where color is the only display technique is probably the black-body radiation spectrum, because of its perceptual ordering and use of color to avoid contrast effects.
So this would presumably mean using one of hot, afmhot, or gist_heat as the default colormap:
This rainbow hue colormap is widely used in visualization, but produces several well-documented artifacts (e.g., Lefkowitz and Herman [1992]; Robertson [1988]; Rogowitz, Ling and Kellogg [1992]). In this MRI image, for example, the colormap creates perceived contours which do not reflect discrete transitions in the data, structures in the data which fall within one of these artificial bands are not represented, and attention is drawn to the yellow areas because they are the brightest, not because they are in any way the most important.
What kind of insane colormap has the property that values spanning the extreme ends of the scale stand out less, and can’t be distinguished as easily as values in the noisy middle? Why, it’s MATLAB’s default colormap, of course!
The main issue here is that in grayscale representation, information about the 'height' of map regions gets lost. The center of the plot (where the highest intensity is found) has the same gray value as the border regions.
That seems to be an objection against using it for 3D CAD? Can you even do things like that in matplotlib? I don't see anything like it in the gallery.
I agree with this comment from the mailing list:
I'd prefer a two-tone colormap as the default (two-distinct tones at the limits with a gradient in-between---dubbed "sequential" in the paper) instead of a three-tone colormap (three-distinct tones---dubbed "diverging" in the paper). (I think this is a more common use case, and I think using a "diverging" colormap effectively requires setting vmin/vmax.)
The coolwarm is meant for "diverging" data, with dark blue negative values, bright white middle 0 values, and dark red positive values (same dark-light-dark problem as jet, but not as bad), while the more common case is "sequential" data from dark zero to bright positive (which is why the first paper above recommends heat/hot when nothing else is known about the use case).
But obviously, nothing will be perfect for every case. Different maps are more appropriate for different situations. Unless there's a way to set different defaults for different types of plots, we just have to pick one that will work better than jet in the common types of plots where people don't change the defaults.
I'm +1 for changing colormap to something more sane than jet. Thanks to everyone for providing links to the relevant resources.
We probably have examples in the test suite that rely on the reference images being rendered in 'jet' - those reference images would have to either be changed, or the default cm switched to jet for testing, and back to the default again post testing.
It should be noted that the default colormap can currently be set via an rcParam. In your matplotlibrc just put:
image.cmap : hot
or
image.cmap : bwr
etc...
If there are places in the code where this cmap setting is not respected (except for instances where it is explicitly specified), those should be considered bugs and should be filed as such.
I don't see any polite way to make such a change (different default colormap). Everyone is used to the nice, colorful jet popping up. I predict that if it is changed, there will be a lot of unhappy users. User code will not behave the way it used to, in a very obvious and major way. Instead of changing the default (at least initially), it would be better to change the gallery examples and documentation to explain and illustrate better colormap choices for various purposes. This can be done incrementally, without breaking any user code.
@efiring, I think that is an excellent idea. We might one day change the default, but this approach might begin the movement from within the userbase. Over time, we might even be able to figure out what a suitable default is.
I still think the default should be changed sooner than later, and that the user who doesn't care enough to change the default isn't going to care if the default changes, but improving the demos is a good idea, too.
It looks like it's not as simple as changing the cmap alone, though, since some have bipolar data and want a diverging colormap, but the colormap isn't currently centered. The seismic colormap highlights the midpoint well. I used this and it worked:
It is actually the norm, not the colormap, that is being centered. You raise a good question. There should be an automatic way (selected by a kwarg) to achieve what you are doing manually, but in general there isn't. I am working on a branch to take care of it, so I expect to have a pull request ready within a few days.
Ok, so actually instead of setting vmax vmin, I should be using something like norm=Normalize(-abs(Z1).max(), abs(Z1).max())?
What will be the syntax for your addition? If the data happens to vary from 4 to 10, and the defined midpoint is 5, we should be able to just say "the midpoint of the colormap is 5" and it will automatically use the extreme values to set the colormap range from 0 to 10.
Ok, so actually instead of setting vmax vmin, I should be using
something like norm=Normalize(-abs(Z1).max(), abs(Z1).max())?
Not necessarily; when vmin, vmax kwargs are available, they are being
passed internally to the norm, so there is no problem with using them as
you did. I was only trying to clarify the terminology, because this is
a somewhat subtle but important point--the distinction between the
actual colormap (cmap kwarg) and the norm, and the fact that they work
together to achieve color mapping.
What will be the syntax for your addition? If the data happens to
vary from 4 to 10, and the defined midpoint is 5, we should be able
to just say "the midpoint of the colormap is 5" and it will
automatically use the extreme values to set the colormap range from 0
to 10.
Yes, that is exactly what I have in mind. I have a branch started to do
this, but it is not ready yet. I am thinking of a kwarg called "vmid"
to go with "vmin" and "vmax", the idea being that if it is not None then
it expands any specified or autoscaled range in the manner you describe.
If you do include vmid and vmax, then vmin is vmid-(vmax-vmid)?
if you include all three, the scale is non-linear, normalized independently from the midpoint to the max point and from the midpoint to the min point? http://stackoverflow.com/q/7404116/125507
If you do include vmid and vmax, then vmin is vmid-(vmax-vmid)?
if you include all three, the scale is non-linear, normalized independently from the midpoint to the max point and from the midpoint to the min point?
No to both. It's much simpler than that. Think of it this way. First,
if either or both of vmin, vmax is provided, then they override the
previous values, which may have resulted from autoscaling. Second, the
upper or lower limit is moved outward as needed to center the scale on
vmid. That's all.
Just thinking out loud, I remember being able to specify just vmin or just vmax and let the autoscaling handle the unspecified end. Is that still the case?
Just thinking out loud, I remember being able to specify just vmin or
just vmax and let the autoscaling handle the unspecified end. Is
that still the case?
Is there something like the Kindleman set available? Do some of the new stylesheets already improve this?
@michaelaye I only noticed this comment of yours today.
I have a version of Kindleman linear lightness colormap in the second half of this notebook tutorial.
Using the same data and function in the notebook I also replicated his circular colormap. it's been sitting on my home computer for a while, I just uploaded it on GitHub here.
Activity
cgohlke commented on May 17, 2012
There have been two related discussions on the [matplotlib-devel] mailing list: Another colormap and Implementation of cubehelix color scheme. Btw, the hot/heat colormaps perform poorly with 3D shading.
endolith commented on May 17, 2012
In what way? Here's jet compared to hot:
endolith commented on May 17, 2012
That seems to be an objection against using it for 3D CAD? Can you even do things like that in matplotlib? I don't see anything like it in the gallery.
I agree with this comment from the mailing list:
The coolwarm is meant for "diverging" data, with dark blue negative values, bright white middle 0 values, and dark red positive values (same dark-light-dark problem as jet, but not as bad), while the more common case is "sequential" data from dark zero to bright positive (which is why the first paper above recommends heat/hot when nothing else is known about the use case).
But obviously, nothing will be perfect for every case. Different maps are more appropriate for different situations. Unless there's a way to set different defaults for different types of plots, we just have to pick one that will work better than jet in the common types of plots where people don't change the defaults.
ivanov commented on May 17, 2012
I'm +1 for changing colormap to something more sane than jet. Thanks to everyone for providing links to the relevant resources.
We probably have examples in the test suite that rely on the reference images being rendered in 'jet' - those reference images would have to either be changed, or the default cm switched to jet for testing, and back to the default again post testing.
It should be noted that the default colormap can currently be set via an rcParam. In your matplotlibrc just put:
or
etc...
If there are places in the code where this cmap setting is not respected (except for instances where it is explicitly specified), those should be considered bugs and should be filed as such.
efiring commented on May 27, 2012
I don't see any polite way to make such a change (different default colormap). Everyone is used to the nice, colorful jet popping up. I predict that if it is changed, there will be a lot of unhappy users. User code will not behave the way it used to, in a very obvious and major way. Instead of changing the default (at least initially), it would be better to change the gallery examples and documentation to explain and illustrate better colormap choices for various purposes. This can be done incrementally, without breaking any user code.
WeatherGod commented on May 27, 2012
@efiring, I think that is an excellent idea. We might one day change the default, but this approach might begin the movement from within the userbase. Over time, we might even be able to figure out what a suitable default is.
endolith commented on May 31, 2012
I still think the default should be changed sooner than later, and that the user who doesn't care enough to change the default isn't going to care if the default changes, but improving the demos is a good idea, too.
It looks like it's not as simple as changing the cmap alone, though, since some have bipolar data and want a diverging colormap, but the colormap isn't currently centered. The seismic colormap highlights the midpoint well. I used this and it worked:
Is there a better way to center the colormap?
efiring commented on May 31, 2012
It is actually the norm, not the colormap, that is being centered. You raise a good question. There should be an automatic way (selected by a kwarg) to achieve what you are doing manually, but in general there isn't. I am working on a branch to take care of it, so I expect to have a pull request ready within a few days.
endolith commented on Jun 4, 2012
Ok, so actually instead of setting vmax vmin, I should be using something like norm=Normalize(-abs(Z1).max(), abs(Z1).max())?
What will be the syntax for your addition? If the data happens to vary from 4 to 10, and the defined midpoint is 5, we should be able to just say "the midpoint of the colormap is 5" and it will automatically use the extreme values to set the colormap range from 0 to 10.
endolith commented on Jun 4, 2012
These are some changes in the branch where I'm changing the example colormaps:https://github.com/endolith/matplotlib/compare/c6fac36ed3c5f14c2a9863d9c68f6a8fa068fcbc (Not sure how else to link to a branch)
efiring commented on Jun 4, 2012
On 06/04/2012 04:46 AM, endolith wrote:
Not necessarily; when vmin, vmax kwargs are available, they are being
passed internally to the norm, so there is no problem with using them as
you did. I was only trying to clarify the terminology, because this is
a somewhat subtle but important point--the distinction between the
actual colormap (cmap kwarg) and the norm, and the fact that they work
together to achieve color mapping.
Yes, that is exactly what I have in mind. I have a branch started to do
this, but it is not ready yet. I am thinking of a kwarg called "vmid"
to go with "vmin" and "vmax", the idea being that if it is not None then
it expands any specified or autoscaled range in the manner you describe.
endolith commented on Jun 5, 2012
That sounds like a good keyword to me.
If you do include vmid and vmax, then vmin is vmid-(vmax-vmid)?
if you include all three, the scale is non-linear, normalized independently from the midpoint to the max point and from the midpoint to the min point? http://stackoverflow.com/q/7404116/125507
efiring commented on Jun 5, 2012
On 06/05/2012 05:18 AM, endolith wrote:
No to both. It's much simpler than that. Think of it this way. First,
if either or both of vmin, vmax is provided, then they override the
previous values, which may have resulted from autoscaling. Second, the
upper or lower limit is moved outward as needed to center the scale on
vmid. That's all.
WeatherGod commented on Jun 6, 2012
Just thinking out loud, I remember being able to specify just vmin or just vmax and let the autoscaling handle the unspecified end. Is that still the case?
efiring commented on Jun 6, 2012
On 06/06/2012 08:37 AM, Benjamin Root wrote:
Yes.
69 remaining items
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
Change default color map (Fix matplotlib#875)
mycarta commented on Jan 29, 2016
@michaelaye I only noticed this comment of yours today.
I have a version of Kindleman linear lightness colormap in the second half of this notebook tutorial.
Using the same data and function in the notebook I also replicated his circular colormap. it's been sitting on my home computer for a while, I just uploaded it on GitHub here.
njsmith commented on Feb 9, 2016
🌟 👯 🌟