Case Study 1: The viridis Revolution — How matplotlib Changed Its Default Colormap
The Problem That Everyone Knew About and Nobody Fixed
For over a decade, the default colormap in matplotlib was jet — the rainbow colormap. Every heatmap, every contour plot, every imshow() call that did not explicitly specify a colormap was rendered in a full-spectrum rainbow: blue at the low end, cycling through cyan, green, yellow, and red at the high end.
The visualization research community knew jet was perceptually broken. David Borland and Russell Taylor had published "Rainbow Color Map (Still) Considered Harmful" in IEEE Computer Graphics and Applications in 2007, documenting the litany of problems: perceptual non-uniformity, false boundaries, meaningless luminance profile, colorblind hostility. Cynthia Brewer's ColorBrewer tool had been providing scientifically tested alternatives since 2002. Colin Ware's textbook had devoted entire sections to the failure modes of rainbow color encoding.
And yet, jet persisted. It was matplotlib's default from the library's creation in 2003. It was what users saw when they followed every tutorial, every Stack Overflow answer, every introductory course. Changing a default in a widely used library is not just a technical decision — it is a social one. Every existing tutorial becomes slightly wrong. Every published figure created with the old default now looks different from figures created with the new one. Users who expect the old behavior are surprised. The cost of switching is real and distributed across millions of users.
So the question was not whether jet was bad — everyone who had studied it agreed it was. The question was whether someone would do the hard work of designing a replacement that was good enough to justify the disruption.
The Design Challenge
In 2014, Nathaniel Smith and Stéfan van der Walt — both core contributors to the scientific Python ecosystem — took on the project. They framed the challenge as a constrained optimization problem. The new default colormap had to satisfy four criteria simultaneously:
Criterion 1: Perceptual uniformity. Equal steps in data value must produce equal perceived color changes across the entire range. This is the fundamental requirement that jet violates. Perceptual uniformity means the colormap is honest — it does not exaggerate some differences while minimizing others.
Criterion 2: Monotonic luminance. The colormap must go steadily from dark to light (or light to dark) across its range, with no reversals. This ensures the colormap is readable in grayscale. When a color figure is printed in black and white, photocopied, or viewed by someone with severe color vision deficiency, the luminance channel must still convey the ordering of the data. Jet fails this criterion catastrophically — its luminance profile has a peak at yellow and valleys at blue and red, making the grayscale version look like a diverging colormap rather than a sequential one.
Criterion 3: Colorblind accessibility. The colormap must remain legible and ordered for viewers with the most common forms of color vision deficiency — deuteranopia and protanopia (red-green confusion). This rules out any colormap that relies on red-green contrast to convey ordering.
Criterion 4: Aesthetic quality. The colormap must look good. This sounds subjective, but it is a practical requirement: if the default colormap is ugly, users will override it, which defeats the purpose of improving the default. The new colormap needed to be attractive enough that users would leave it in place.
Smith and van der Walt recognized that these four criteria are not independent — they interact in complicated ways. A colormap with extreme perceptual uniformity in CIE LAB space might look washed out or unpleasant. A colormap that is strikingly beautiful might achieve its beauty through the kind of luminance non-monotonicity that jet exhibits. The challenge was finding a colormap that satisfied all four constraints simultaneously.
The Design Process
Smith and van der Walt did not simply pick colors and hope for the best. They treated the colormap design as a computational optimization in CIE CAM02-UCS space (a perceptual color space more accurate than CIE LAB for this purpose). Their process involved several stages.
Stage 1: Defining the design space. They parameterized candidate colormaps as curves through a perceptual color space. Each candidate was defined by a set of control points that specified its trajectory through the space — what hues it visited, how luminance changed, and how saturation varied.
Stage 2: Computing perceptual properties. For each candidate, they computed the luminance profile (is it monotonic?), the local perceptual contrast (how much does the color change per data step, at every point in the range?), and the colorblind simulation (what does the colormap look like under deuteranopia and protanopia?).
Stage 3: Iterative refinement. Smith and van der Walt generated hundreds of candidate colormaps and evaluated them against the four criteria. They discarded colormaps that failed any criterion and refined those that came close. The process was part automated optimization, part expert judgment about which colors "look right" together.
Stage 4: Community feedback. The candidates were presented to the matplotlib community for evaluation. The designers posted detailed comparisons showing each candidate's luminance profile, its appearance under colorblind simulation, its grayscale version, and its visual quality on sample data. This transparency was critical — it meant the community could evaluate the choices using the same perceptual criteria, not just personal preference.
The process produced not one but four new colormaps: viridis (the new default — dark purple through blue, green, to bright yellow), plasma (blue-purple through red to yellow), inferno (near-black through red and orange to bright yellow), and magma (near-black through purple and pink to light yellow). All four satisfy the design criteria. viridis was chosen as the default because it offered the best balance of perceptual uniformity, aesthetic appeal, and distinguishability at both ends of the range.
A fifth colormap, cividis, was added later, designed by Jamie Nuñez specifically for deuteranopia accessibility. cividis uses only the blue-yellow axis, which is fully visible to red-green colorblind viewers, at the cost of a somewhat narrower hue range.
The Transition
matplotlib 2.0, released in January 2017, shipped with viridis as the default colormap. (The colormap itself was available in matplotlib 1.5 as a named option, but 2.0 was the release where it became the default.) This meant that every new matplotlib figure — every tutorial, every quick plot, every exploratory notebook — would now use viridis unless the user explicitly chose something else.
The transition was not without friction. Users who had been relying on jet for years found that their existing scripts produced different-looking figures. Some complained that viridis was "less colorful" or "harder to read" — responses that, ironically, often reflected the very perceptual biases that jet had trained into them. Users accustomed to the false "detail" of rainbow's perceptual artifacts perceived the honest uniformity of viridis as a loss of information.
The matplotlib team handled the transition thoughtfully. They provided detailed documentation explaining the change and its scientific rationale. They kept jet available as a named colormap — nothing was removed. The SciPy 2015 talk by Smith and van der Walt, which laid out the evidence in accessible terms, became one of the most watched SciPy talks ever and served as the primary reference when users asked "why did the colors change?"
The Impact
The impact of the default change was profound and is difficult to overstate.
Scale of effect: matplotlib is used to create tens of millions of figures every year, in academic papers, data science notebooks, corporate reports, and educational materials. By changing the default, every figure that used default settings was immediately more perceptually accurate and more accessible. The users who benefited most were those who never thought about color at all — the "I just called plt.imshow() and used whatever came out" users. These users went from producing perceptually dishonest rainbow figures to producing perceptually honest viridis figures without changing a single line of code.
Cascade through the ecosystem: After matplotlib's change, other libraries followed. seaborn adopted viridis-family palettes as defaults. Plotly, Bokeh, and other libraries reconsidered their own defaults. The ripple effect reached beyond Python — MATLAB changed its default from jet to parula (a similar perceptually uniform colormap) in 2014, and R's ggplot2 ecosystem saw increased adoption of viridis through the viridis R package.
Normative shift: Perhaps most importantly, the change shifted the community conversation. Before viridis, the burden was on the informed user to opt out of the broken default. After viridis, the default was defensible, and choosing jet required a deliberate (and increasingly awkward) decision. Conference presentations that used rainbow colormaps began to draw audience questions and peer review comments. "Why did you use jet?" became a legitimate question in manuscript review. The social norm had shifted.
Educational impact: Every matplotlib tutorial written after 2017 shows viridis by default. Students learning data visualization for the first time never internalize jet as the "normal" look of a heatmap. They internalize viridis — a perceptually uniform, colorblind-safe colormap — and that becomes their baseline expectation. This is how you change a field: not by educating every individual, but by changing the defaults so that the right behavior requires no extra effort.
Lessons for Visualization Practice
The viridis story illustrates several principles that extend well beyond colormaps.
Defaults matter enormously. Most users will never change the default settings. If the default is bad, most output will be bad. If the default is good, most output will be good. This applies to colormaps, but also to axis labels, font sizes, figure dimensions, and every other default in your visualization toolkit. Chapter 12 (Customization Mastery) and Chapter 32 (Theming and Branding) will revisit this principle from a practical implementation perspective.
Design decisions should be grounded in evidence, not taste. The viridis designers did not choose colors they liked — they defined measurable criteria (perceptual uniformity, luminance monotonicity, colorblind accessibility) and optimized against them. You can do the same with any color decision: convert to grayscale, run a colorblind simulation, check contrast ratios. These tests are objective and repeatable.
Transparency enables adoption. By publishing the design criteria, the evaluation data, and the comparison visualizations, Smith and van der Walt gave the community the information needed to evaluate the change on its merits. When the change was criticized, the evidence was available. Transparency turned a potentially contentious default change into an educational moment.
Better defaults are more ethical. jet was not just ugly — it was misleading. It introduced false features into data and excluded colorblind viewers. Replacing it with viridis was an ethical improvement as much as an aesthetic one. Every time you make a chart more perceptually honest and more accessible, you are doing work that matters beyond aesthetics.
A Note on What viridis Does Not Fix
viridis is an excellent default, but it is not a universal solution. It is a sequential colormap, appropriate for data that goes from low to high. It is not appropriate for diverging data (use RdBu, coolwarm, or a similar palette). It is not appropriate for categorical data (use Set2, tab10, or similar). And it does not free you from thinking about color — it frees you from thinking about the specific problem of perceptually uniform sequential colormaps, which is only one piece of the color puzzle.
The broader lesson of this chapter stands: every color choice is a design decision. viridis is a good default. But understanding why it is good — and understanding when to choose something different — is your responsibility.
Discussion Questions
-
The Default Power: Consider another default setting in a widely used tool (it does not need to be a visualization tool). How does the default shape user behavior? If the default were changed, what would the impact be?
-
Resistance to Change: Some users resisted the switch from jet to viridis, arguing that jet showed "more detail." Given what you know about perceptual non-uniformity and false boundaries, why is this argument incorrect? How would you explain it to a skeptical colleague?
-
The Informed Minority Problem: Before the default change, the situation was: a minority of informed users knew jet was bad and chose alternatives; the majority of users accepted the default. After the change, the majority got a good default automatically. What other areas of data visualization (or data science more broadly) suffer from a similar "informed minority" problem?
-
Trade-offs in the Design Criteria: Smith and van der Walt's four criteria (perceptual uniformity, luminance monotonicity, colorblind accessibility, aesthetic quality) sometimes conflict. Can you think of a scenario where maximizing one criterion would require compromising another? How did viridis navigate this trade-off?
-
The Cultural Impact of Defaults: The viridis default changed what "a matplotlib figure" looks like. This has cultural implications — scientific papers, classroom materials, and news graphics produced in matplotlib now share a visual language. Is this homogeneity beneficial (consistency, accessibility) or harmful (lack of visual diversity, difficulty distinguishing sources)? Or both?
Return to the chapter text or proceed to Case Study 2.