Skip to content

Replace "jet" as the default colormap #875

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
endolith opened this issue May 17, 2012 · 68 comments
Closed

Replace "jet" as the default colormap #875

endolith opened this issue May 17, 2012 · 68 comments

Comments

@endolith
Copy link
Contributor

endolith commented May 17, 2012

This is subjective: a matter of sane defaults vs consistency with matlab, but here are the arguments against jet as default:

Rainbow Color Map (Still) Considered Harmful:

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:

hot, afmhot, and gist_heat

How NOT to Lie with Visualization:

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.

Let’s talk colormaps:

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 'jet' colormap must die!:

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.

@cgohlke
Copy link
Contributor

cgohlke commented 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
Copy link
Contributor Author

Btw, the hot/heat colormaps perform poorly with 3D shading.

In what way? Here's jet compared to hot:

jet bump
hot bump

@endolith
Copy link
Contributor Author

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.

@ivanov
Copy link
Member

ivanov commented 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:

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.

@efiring
Copy link
Member

efiring commented 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
Copy link
Member

@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
Copy link
Contributor Author

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:

vmax = max( amax(Z), -amin(Z)), 
vmin = min(-amax(Z),  amin(Z)),

Is there a better way to center the colormap?

off-center
centered

@efiring
Copy link
Member

efiring commented 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
Copy link
Contributor Author

endolith commented 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
Copy link
Contributor Author

endolith commented 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
Copy link
Member

efiring commented Jun 4, 2012

On 06/04/2012 04:46 AM, endolith wrote:

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.

@endolith
Copy link
Contributor Author

endolith commented 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
Copy link
Member

efiring commented Jun 5, 2012

On 06/05/2012 05:18 AM, endolith wrote:

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?

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
Copy link
Member

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
Copy link
Member

efiring commented Jun 6, 2012

On 06/06/2012 08:37 AM, Benjamin Root wrote:

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?

Yes.

@pelson
Copy link
Member

pelson commented Jun 13, 2012

Just wanted to note here that I have a SymmetricNorm class which auto-scales evenly around a centre point.
It sounds like it could do the trick (and potentially avoid mutually exclusive keywords) and I'd be happy to share.

@endolith
Copy link
Contributor Author

Maybe the symmetric norm stuff should be added under #632?

@efiring
Copy link
Member

efiring commented Aug 13, 2012

Closed after #921 merge

@efiring efiring closed this as completed Aug 13, 2012
@endolith
Copy link
Contributor Author

(I'm still in favor of changing the default, for the record.) :)

@tacaswell
Copy link
Member

I (very belatedly) add a vote for changing the default color map.

@franktoffel
Copy link

FYI, "jet" won't be the default colormap for MATLAB anymore. The new release has finally improved this and other related aspects. http://www.mathworks.es/products/matlab/matlab-graphics/#new_look_for_matlab_graphics

@endolith
Copy link
Contributor Author

There is also a new default colormap in R2014b called parula [named after a similarly-colored bird?]. The colors in the parula colormap are ordered from dark to light and are perceptually uniform. Smooth changes in the data appear as smooth changes in color, while sharp changes in the data appear as sharp changes in color.

colormap_parula

Well, at least someone is doing it. Hopefully open source projects copy this now instead of copying jet?

@tacaswell
Copy link
Member

Regardless, changing the default color map is still an api break which we won't do until 2.0.

@michaelaye
Copy link

As this point was a bit lost in the discussion if to break the API, which of the MPL's colormaps would be considered as the best alternative to jet these days? Is there something like the Kindleman set available? Do some of the new stylesheets already improve this?

@NelleV
Copy link
Member

NelleV commented Oct 14, 2014

As this point was a bit lost in the discussion if to break the API,
which of the MPL's colormaps would be considered as the best
alternative these days?

Probably gray_r or gray


Reply to this email directly or view it on GitHub
#875 (comment)
.

@tacaswell
Copy link
Member

👍 on gray.

The style module does take care of this in principle via the image.cmap rcparam. mpl.style.use() can look up arbitrary paths, including URLs. A trick from @danielballan is to put a stlye-file in a gist: https://gist.github.com/danielballan/be066529de85e87a5fe7

@WeatherGod
Copy link
Member

Thanks Paul, I was wondering about the length of that URL...

Anyway, the tl;dr; of the video is that, yes, Lab space does measure color
distances better than XYZ, but Stefan and Nathanial didn't use XYZ. They
used newer model that had much lower errors for both nearby and far away
colors. They even show examples of parula having apparent gradients that
didn't really exist.

On Wed, Jul 15, 2015 at 3:13 PM, Paul Ivanov notifications@github.com
wrote:

(Ben, I took the liberty of updating your link to the direct youtube one -
google doesn't play nicely when you try to copy-link from search results)


Reply to this email directly or view it on GitHub
#875 (comment)
.

@njsmith
Copy link

njsmith commented Jul 15, 2015

@scottsievert: Is there text somewhere saying that XYZ space was used to calculate perceptual differences? If so it'd be good to know so we can correct it -- we used CAM02-UCS, which is a perceptually uniform space that improves on CIEL_a_b_. To get to either CAM02-UCS and CIEL_a_b_ space you have to pass through XYZ -- here's the transformation graph supported by colorspacious 0.1.0 --

colorspacious

but that's an implementation detail...

[Edit for clarify: CAM02-UCS is the J'a'b' node in the lower-right.]

@stsievert
Copy link

Got it. In your talk mentioned above, you referred to the XYZ space more often and I assumed that's what you were using to calculate the perceptual differences. It's good to know otherwise and I'll trust you on this.

@njsmith
Copy link

njsmith commented Jul 15, 2015

Ah, gotcha, right, that could definitely have been clearer. Something to
keep in mind if I end up giving the talk again :-)

On Wed, Jul 15, 2015 at 2:44 PM, Scott S. notifications@github.com wrote:

Got it. In your talk https://www.youtube.com/watch?v=xAoljeRJ3lU
mentioned above, you referred to the XYZ space more often and I assumed
that's what you were using to calculate the perceptual differences. It's
good to know otherwise and I'll trust you on this.


Reply to this email directly or view it on GitHub
#875 (comment)
.

Nathaniel J. Smith -- http://vorpus.org

@stefanv
Copy link
Contributor

stefanv commented Jul 30, 2015

See also #4707

@mdboom mdboom modified the milestones: Color overhaul, next major release (2.0) Oct 8, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 16, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 17, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 23, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 23, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 25, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 27, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Nov 27, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 14, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 14, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 14, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 17, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 31, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Dec 31, 2015
mdboom added a commit to mdboom/matplotlib that referenced this issue Jan 4, 2016
@mycarta
Copy link

mycarta commented Jan 29, 2016

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.

@njsmith
Copy link

njsmith commented Feb 9, 2016

🌟 👯 🌟

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests