Colormaps#

HoloViews supports a wide range of colormaps, each of which allow you to translate numerical data values into visible colors in a plot. Here we will review all the colormaps provided for HoloViews and discuss when and how to use them.

The Styling_Plots user guide discusses how to specify any of the colormaps discussed here, using the cmap style option:

import numpy as np
import holoviews as hv
hv.extension('matplotlib')

ls  = np.linspace(0, 10, 400)
x,y = np.meshgrid(ls, ls)
img = hv.Image(np.sin(x)*np.cos(y)+0.1*np.random.rand(400,400), 
               bounds=(-20,-20,20,20)).opts(colorbar=True, xaxis=None, yaxis=None)

hv.Layout([img.relabel(c).opts(cmap=c) for c in ['gray','PiYG','flag','Set1']])

As you can see, the colormap you choose can dramatically change how your data appears. A well-chosen colormap can help guide the user to notice the features of the data you want to highlight, while a poorly chosen colormap can completely obscure the data and lead to erroneous conclusions. E.g. the low levels of noise present in this data are very difficult to see in A and B, but they completely dominate the plot in C and are visible only at specific (presumably arbitrary) value levels that correspond to color transitions in D. Thus it is important to choose colormaps very carefully!

Note that the cmap style option used above is applied by the underlying plotting library, not by HoloViews itself. In the above example, Matplotlib uses it as the colormap constructs the image, whereas a Bokeh version of the same plot would provide the colormap to the Bokeh JavaScript code running in the local web browser, which allows the user to control the colormap dynamically in some cases.

Colormaps can also be used with the Datashader shade() operation, in which the provided cmap is applied by Datashader to create an image before passing the image to the plotting library, which enables additional Datashader features but disables client-side features like colorbars and dynamic colormapping on display.

Available colormaps#

As outlined in Styling_Plots, you can easily make your own custom colormaps, but it’s quite difficult to ensure that a custom map is designed well, so it’s generally best to choose an existing, well-tested colormap. Here we will show the many different types of colormaps available, discussing each category and how to use that type of map. The ones shown here are those that are available by name, if the corresponding provider has been installed. E.g. those labelled “(bokeh)” will only be available if Bokeh is installed.

Most of these colormaps will work best on either a light or a dark background, but not both. To faithfully and intuitively represent monotonically increasing values, you will generally want a colormap where the lowest values are similar in tone to the page background, and higher values become more perceptually salient compared to the page background. To let you match the colormap to the page, the maps listed below have a variant suffixed with _r (not shown), which is the same map but with the reverse order.

from math import ceil
from holoviews.plotting.util import process_cmap

colormaps = hv.plotting.list_cmaps()
spacing = np.linspace(0, 1, 64)[np.newaxis]
opt_kwargs = dict(aspect=6, xaxis=None, yaxis=None, sublabel_format='')

def filter_cmaps(category):
    return hv.plotting.util.list_cmaps(records=True,category=category,reverse=False)

def cmap_examples(category,cols=4):
    cms = filter_cmaps(category)
    n = len(cms)*1.0
    c=ceil(n/cols) if n>cols else cols
    bars = [hv.Image(spacing, ydensity=1, label="{0} ({1})".format(r.name,r.provider))\
            .opts(cmap=process_cmap(r.name,provider=r.provider), **opt_kwargs)
           for r in cms]
    return hv.Layout(bars).opts(vspace=0.1, hspace=0.1, transpose=(n>cols)).cols(c)

Perceptually uniform sequential colormaps#

Useful for the typical case of having increasing numeric values that you want to distinguish without bias for any specific value. The colormaps in this category are designed to represent similar distances in value space (e.g. a numerical difference from 0.2 to 0.4, or one from 0.4 to 0.6, with similar differences in what we perceive visually).

For detailed discussions of this important issue, see Kovesi, van der Walt & Smith, and Karpov, who each argue for different color spaces and criteria for evaluating colormaps and thus develop different types of colormaps. Despite the disagreements over important details, all of the maps here will be significantly more uniform than an arbitrary map designed without perceptual criteria, such as those in “Other Sequential” below, and thus these colormaps represent good default choices in most cases.

When choosing one of these, be sure to consider whether you wish your page background to be distinguishable from a color in the colormap. If your data covers the entire plot, then using the background color is fine, but if you need the background color to show through (e.g. to show missing values), then you should avoid maps that include black (fire, magma, inferno, gray, k*) on a black page or white (fire,gray) on a white page.

cmap_examples('Uniform Sequential')

Diverging colormaps#

Useful to highlight differences from a neutral central value, which is typically chosen to match the page background (e.g. white or yellow when using a white page, or black when using a black page).

Most of the diverging maps listed here were not developed to match a definition of perceptual uniformity, but those coming from colorcet were and should thus be preferred over the rest (which can be obtained by specifying Uniform Diverging here).

Some of these colormaps include both red and green, making them ambiguous for people with the most common types of colorblindness, and should thus be avoided where possible.

cmap_examples('Diverging')

Rainbow colormaps#

Rainbow-like colormaps convey value primarily through color rather than luminance. They result in eye-catching plots, but because rainbow colors form a continuous, cyclic spectrum, they can be ambiguous about which values are higher than the others. Most of them are also highly perceptually non-uniform, with pronounced banding that makes some values easily distinguished from their neighbors, and other wide ranges of values nearly indistinguishable (e.g. the greenish colors in the gist_rainbow and jet colormaps).

If you do want a rainbow colormap, please consider using one of the three perceptually uniform versions (category Uniform Rainbow) included here:

  • colorwheel (colorcet): for cyclic values like angles and longitudes that wrap around to the same value at the end of the range (notice that the lowest and highest colors are both blue)

  • rainbow (colorcet): for monotonically and uniformly increasing values (skips purple region to avoid ordering ambiguity)

  • isolum (colorcet): for monotonically and uniformly increasing values, but only uses hue changes, with a constant lightness. Nearly all the other maps are dominated by changes in lightness, which is much more perceptually salient than strict changes in hue as in this map. Useful as a counterpart and illustration of the role of lightness.

Of course, rainbow colormaps have the disadvantage that they are inherently unsuitable for most colorblind viewers, because they require viewers to distinguish between red and green to determine value.

cmap_examples('Rainbow')

Categorical colormaps#

Primarily useful as color cycles rather than colormaps, i.e. as a list of discrete color values, not a continuous range of colors. Will produce discrete banding when used on continuous values, like in a geographic contour plot, but if that effect is desired it’s probably better to use color_levels with a sequential colormap to be able to control how many levels there are and give them a natural ordering.

Most of these color sets are constructed by hand, with a relatively small number of distinct colors. If you want a larger number of colors, the glasbey_ categorical maps from Colorcet are generated using a systematic procedure based on sampling a perceptual space for widely separated colors, which allows large numbers of categories to be distinguished from each other.

The glasbey_hv colors have the useful property that they share the same first 12 colors as the default HoloViews color cycle, which means that if you want the same colors as usual but with more available when needed, you can switch the HoloViews default using hv.Cycle.default_cycles['default_colors']=colorcet.glasbey_hv.

cmap_examples('Categorical')

Mono Sequential colormaps#

Monotonically increasing values that serve the same purpose as Uniform Sequential (above), but are not specifically constructed to be perceptually uniform. Useful when you want to fit into a particular visual theme or color scheme, or when you want to color entire plots differently from other entire plots (e.g. to provide a visual “traffic light” indicator for the entire plot, making some plots stand out relative to others). If you just need a single colormap, try to select a Uniform Sequential map instead of these.

cmap_examples('Mono Sequential')

Other Sequential colormaps#

Other sequential colormaps are included, but are not meant for general use. Some of these have a very high degree of perceptual non-uniformity, making them highly misleading. E.g. the hot (matplotlib) colormap includes pronounced banding (with sharp perceptual discontinuities and long stretches of indistinguishable colors); consider using the perceptually uniform fire (colorcet) map instead. Others like gray largely duplicate maps in the other categories above, and so can cause confusion. The Uniform Sequential maps, or if necessary Mono Sequential, are generally good alternatives to these.

cmap_examples('Other Sequential')

Miscellaneous colormaps#

There are a variety of other colormaps not fitting into the categories above, mostly of limited usefuless. Exceptions include the flag and prism (matplotlib) colormaps that could be useful for highlighting local changes in value (details), with no information about global changes in value (due to the repeating colors).

cmap_examples('Miscellaneous')

See the Styling_Plots user guide for how these colormaps can be used to control how your data is plotted.

Querying and filtering the list of colormaps#

For most purposes, you can just pick one of the colormaps above for a given plot. However, HoloViews is very often used to build applications and dashboards, many of which include a “colormap” selection widget. Because there are so many colormaps available, most of which are inappropriate for any specific plot, it’s useful to be able to pull up a list of all the colormaps that are suitable for the specific type of plot used in the app.

To allow such filtering, HoloViews stores the following information about each named colormap, matched by substring:

  • name: string name for the colormap

  • category: Type of map by intended use or purpose (‘[Uniform|Mono|Other ]Sequential’, ‘[Uniform ]Diverging’, ‘[Uniform ]Rainbow’, ‘[Uniform ]Categorical’, or ‘Miscellaneous’)

  • provider: package offering the colormap (‘matplotlib’, ‘bokeh’, or ‘colorcet’)

  • source: original source or creator of the colormaps (‘cet’, ‘colorbrewer’, ‘d3’, ‘bids’,’misc’)

  • bg: base/background color expected for the map (‘light’,’dark’,’medium’,’any’)

  • reverse: whether the colormap name includes _r indicating that it is a reverse of a base map (True, False)

The hv.plotting.list_cmaps() function used above can select a subset of the available colormaps by filtering based on the above values:

list_cmaps(provider, records, name, category, source, bg, reverse)

The examples below should make it clear how to use this function.

from holoviews.plotting import list_cmaps
def format_list(l):
    print(' '.join(sorted([k for k in l])))

All named colormaps provided by colorcet, reversed:

format_list(list_cmaps(provider='colorcet',reverse=True))
bgy_r bgyw_r bjy_r bkr_r bky_r blues_r bmw_r bmy_r bwy_r colorwheel_r coolwarm_r cwr_r cyclic_isoluminant_r dimgray_r fire_r glasbey_cool_r glasbey_dark_r glasbey_hv_r glasbey_light_r glasbey_r glasbey_warm_r gouldian_r gray_r gwv_r isolum_r kb_r kbc_r kbgyw_r kg_r kgy_r kr_r linear_blue_5_95_c73_r linear_green_5_95_c69_r rainbow4_r rainbow_r

All non-reversed colormaps provided by matplotlib and originating from d3 that have 20 in their names:

format_list(list_cmaps(name='20', source='d3', provider='matplotlib', reverse=False))
Grays cet_CET_C1 cet_CET_C10 cet_CET_C10s cet_CET_C11 cet_CET_C11s cet_CET_C1s cet_CET_C2 cet_CET_C2s cet_CET_C3 cet_CET_C3s cet_CET_C4 cet_CET_C4s cet_CET_C5 cet_CET_C5s cet_CET_C6 cet_CET_C6s cet_CET_C7 cet_CET_C7s cet_CET_C8 cet_CET_C8s cet_CET_C9 cet_CET_C9s cet_CET_CBC1 cet_CET_CBC2 cet_CET_CBD1 cet_CET_CBD2 cet_CET_CBL1 cet_CET_CBL2 cet_CET_CBL3 cet_CET_CBL4 cet_CET_CBTC1 cet_CET_CBTC2 cet_CET_CBTD1 cet_CET_CBTL1 cet_CET_CBTL2 cet_CET_CBTL3 cet_CET_CBTL4 cet_CET_D1 cet_CET_D10 cet_CET_D11 cet_CET_D12 cet_CET_D13 cet_CET_D1A cet_CET_D2 cet_CET_D3 cet_CET_D4 cet_CET_D6 cet_CET_D7 cet_CET_D8 cet_CET_D9 cet_CET_I1 cet_CET_I2 cet_CET_I3 cet_CET_L1 cet_CET_L10 cet_CET_L11 cet_CET_L12 cet_CET_L13 cet_CET_L14 cet_CET_L15 cet_CET_L16 cet_CET_L17 cet_CET_L18 cet_CET_L19 cet_CET_L2 cet_CET_L20 cet_CET_L3 cet_CET_L4 cet_CET_L5 cet_CET_L6 cet_CET_L7 cet_CET_L8 cet_CET_L9 cet_CET_R1 cet_CET_R2 cet_CET_R3 cet_CET_R4 cet_bgy cet_bgyw cet_bjy cet_bkr cet_bky cet_blues cet_bmw cet_bmy cet_bwy cet_circle_mgbm_67_c31 cet_circle_mgbm_67_c31_s25 cet_colorwheel cet_coolwarm cet_cwr cet_cyclic_bgrmb_35_70_c75 cet_cyclic_bgrmb_35_70_c75_s25 cet_cyclic_grey_15_85_c0 cet_cyclic_grey_15_85_c0_s25 cet_cyclic_isoluminant cet_cyclic_mrybm_35_75_c68 cet_cyclic_mrybm_35_75_c68_s25 cet_cyclic_mybm_20_100_c48 cet_cyclic_mybm_20_100_c48_s25 cet_cyclic_mygbm_30_95_c78 cet_cyclic_mygbm_30_95_c78_s25 cet_cyclic_mygbm_50_90_c46 cet_cyclic_mygbm_50_90_c46_s25 cet_cyclic_protanopic_deuteranopic_bwyk_16_96_c31 cet_cyclic_protanopic_deuteranopic_wywb_55_96_c33 cet_cyclic_rygcbmr_50_90_c64 cet_cyclic_rygcbmr_50_90_c64_s25 cet_cyclic_tritanopic_cwrk_40_100_c20 cet_cyclic_tritanopic_wrwc_70_100_c20 cet_cyclic_wrkbw_10_90_c43 cet_cyclic_wrkbw_10_90_c43_s25 cet_cyclic_wrwbw_40_90_c42 cet_cyclic_wrwbw_40_90_c42_s25 cet_cyclic_ymcgy_60_90_c67 cet_cyclic_ymcgy_60_90_c67_s25 cet_dimgray cet_diverging_bkr_55_10_c35 cet_diverging_bky_60_10_c30 cet_diverging_bwg_20_95_c41 cet_diverging_bwr_20_95_c54 cet_diverging_bwr_40_95_c42 cet_diverging_bwr_55_98_c37 cet_diverging_cwm_80_100_c22 cet_diverging_gkr_60_10_c40 cet_diverging_gwr_55_95_c38 cet_diverging_gwv_55_95_c39 cet_diverging_isoluminant_cjm_75_c23 cet_diverging_isoluminant_cjm_75_c24 cet_diverging_isoluminant_cjo_70_c25 cet_diverging_linear_bjr_30_55_c53 cet_diverging_linear_bjy_30_90_c45 cet_diverging_linear_protanopic_deuteranopic_bjy_57_89_c34 cet_diverging_protanopic_deuteranopic_bwy_60_95_c32 cet_diverging_rainbow_bgymr_45_85_c67 cet_diverging_tritanopic_cwr_75_98_c20 cet_fire cet_glasbey cet_glasbey_bw cet_glasbey_bw_minc_20 cet_glasbey_bw_minc_20_hue_150_280 cet_glasbey_bw_minc_20_hue_330_100 cet_glasbey_bw_minc_20_maxl_70 cet_glasbey_bw_minc_20_minl_30 cet_glasbey_category10 cet_glasbey_cool cet_glasbey_dark cet_glasbey_hv cet_glasbey_light cet_glasbey_warm cet_gouldian cet_gray cet_gwv cet_isolum cet_isoluminant_cgo_70_c39 cet_isoluminant_cgo_80_c38 cet_isoluminant_cm_70_c39 cet_kb cet_kbc cet_kbgyw cet_kg cet_kgy cet_kr cet_linear_bgy_10_95_c74 cet_linear_bgyw_15_100_c67 cet_linear_bgyw_15_100_c68 cet_linear_bgyw_20_98_c66 cet_linear_blue_5_95_c73 cet_linear_blue_95_50_c20 cet_linear_bmw_5_95_c86 cet_linear_bmw_5_95_c89 cet_linear_bmy_10_95_c71 cet_linear_bmy_10_95_c78 cet_linear_gow_60_85_c27 cet_linear_gow_65_90_c35 cet_linear_green_5_95_c69 cet_linear_grey_0_100_c0 cet_linear_grey_10_95_c0 cet_linear_kbc_5_95_c73 cet_linear_kbgoy_20_95_c57 cet_linear_kbgyw_10_98_c63 cet_linear_kbgyw_5_98_c62 cet_linear_kgy_5_95_c69 cet_linear_kry_0_97_c73 cet_linear_kry_5_95_c72 cet_linear_kry_5_98_c75 cet_linear_kryw_0_100_c71 cet_linear_kryw_5_100_c64 cet_linear_kryw_5_100_c67 cet_linear_protanopic_deuteranopic_kbjyw_5_95_c25 cet_linear_protanopic_deuteranopic_kbw_5_95_c34 cet_linear_protanopic_deuteranopic_kbw_5_98_c40 cet_linear_protanopic_deuteranopic_kyw_5_95_c49 cet_linear_ternary_blue_0_44_c57 cet_linear_ternary_green_0_46_c42 cet_linear_ternary_red_0_50_c52 cet_linear_tritanopic_kcw_5_95_c22 cet_linear_tritanopic_krjcw_5_95_c24 cet_linear_tritanopic_krjcw_5_98_c46 cet_linear_tritanopic_krw_5_95_c46 cet_linear_wcmr_100_45_c42 cet_linear_worb_100_25_c53 cet_linear_wyor_100_45_c55 cet_rainbow cet_rainbow4 cet_rainbow_bgyr_10_90_c83 cet_rainbow_bgyr_35_85_c72 cet_rainbow_bgyr_35_85_c73 cet_rainbow_bgyrm_35_85_c69 cet_rainbow_bgyrm_35_85_c71 gist_grey gist_yerg grey tab20 tab20b tab20c turbo twilight twilight_shifted

Colormaps provided by Bokeh that are suitable for dark-colored (e.g. black) backgrounds:

format_list(list_cmaps(category='Other Sequential', bg='dark'))
afmhot binary_r bone gist_gray gist_heat gist_yarg_r gray hot pink

Notice how some of these have _r, because those two natively start with light values and must be reversed to be suitable on a dark background. In this case the results for bg='light' are the complementary set of colormaps:

format_list(list_cmaps(category='Other Sequential', bg='light'))
afmhot_r binary bone_r gist_gray_r gist_heat_r gist_yarg gray_r hot_r pink_r

However, Diverging colormaps do not change their background color when reversed, and so requesting a light or dark background gives different maps altogether (depending on their central color):

format_list(list_cmaps(category='Diverging', bg='dark'))
bkr bky bwy_r coolwarm_r cwr_r gwv_r
format_list(list_cmaps(category='Diverging', bg='light'))
BrBG BrBG_r PRGn PRGn_r PiYG PiYG_r PuOr PuOr_r RdBu RdBu_r RdGy RdGy_r RdYlBu RdYlBu_r RdYlGn RdYlGn_r Spectral Spectral_r bkr_r bky_r bwr bwr_r bwy coolwarm coolwarm_r cwr gwv seismic seismic_r

Matches are done by substring, so all sequential colormaps suitable for dark or any backgrounds can be obtained with:

format_list(list_cmaps(category='Sequential', bg='a'))
Blues_r BuGn_r BuPu_r GnBu_r Greens_r Greys_r Inferno Magma OrRd_r Oranges_r Plasma PuBuGn_r PuBu_r PuRd_r Purples_r RdPu_r Reds_r Viridis Wistia Wistia_r YlGnBu_r YlGn_r YlOrBr_r YlOrRd_r afmhot autumn autumn_r bgy bgyw binary_r blues blues_r bmw bmy bone cividis cool cool_r copper copper_r dimgray fire gist_gray gist_heat gist_yarg_r gray hot inferno kb kb_r kbc kg kg_r kgy kr kr_r magma pink plasma spring spring_r summer summer_r viridis winter winter_r

In the examples above, list_cmaps is returning just the colormap name, but if you want to work with the filter information yourself to do more complex queries, you can ask that it return the full records as namedtuples instead:

list_cmaps(category="Uniform Sequential", provider='bokeh', bg='light', records=True)
[CMapInfo(name='Inferno_r', provider='bokeh', category='Uniform Sequential', source='bids', bg='light'),
 CMapInfo(name='Magma_r', provider='bokeh', category='Uniform Sequential', source='bids', bg='light'),
 CMapInfo(name='Plasma_r', provider='bokeh', category='Uniform Sequential', source='bids', bg='light'),
 CMapInfo(name='Viridis_r', provider='bokeh', category='Uniform Sequential', source='bids', bg='light')]

In addition to populating GUI widgets, another way to use this filtering is to systematically evaluate how your plot will look with a variety of different colormaps of the same type:

hv.Layout([img.relabel(c).opts(cmap=c, colorbar=False, sublabel_format='') 
           for c in list_cmaps(category='Diverging', bg='light', reverse=False)][:14])\
    .opts(vspace=0.1, hspace=0.1).cols(7)

You could also consider filtering on the actual values in the colormap, perhaps to ensure that the specific background color you are using is not present in the colormap. For this you can use the hv.plotting.util.process_cmap function to look up the actual colormap values by name and provider.

This web page was generated from a Jupyter notebook and not all interactivity will work on this website. Right click to download and run locally for full Python-backed interactivity.