1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
"""
.. _colormap_example:
Colormap Choices
~~~~~~~~~~~~~~~~
Use a Matplotlib, Colorcet, cmocean, or custom colormap when plotting scalar
values.
"""
from __future__ import annotations
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
import numpy as np
import pyvista as pv
from pyvista import examples
# %%
# Any colormap built for ``matplotlib``, ``colorcet``, or ``cmocean`` is fully
# compatible with PyVista. Colormaps are typically specified by passing the
# string name of the colormap to the plotting routine via the ``cmap``
# argument.
#
# See `Matplotlib's complete list of available colormaps`_,
# `Colorcet's complete list`_, and `cmocean's complete list`_.
#
# .. _Matplotlib's complete list of available colormaps: https://matplotlib.org/tutorials/colors/colormaps.html
# .. _Colorcet's complete list: https://colorcet.holoviz.org/user_guide/index.html
# .. _cmocean's complete list: https://matplotlib.org/cmocean/
# %%
# Custom Made Colormaps
# +++++++++++++++++++++
#
# To get started using a custom colormap, download some data with scalar values to
# plot.
mesh = examples.download_st_helens().warp_by_scalar()
# Add scalar array with range (0, 100) that correlates with elevation
mesh['values'] = pv.plotting.tools.normalize(mesh['Elevation']) * 100
# %%
# Build a custom colormap - here we make a colormap with 5 discrete colors
# and we specify the ranges where those colors fall:
# Define the colors we want to use
blue = np.array([12 / 256, 238 / 256, 246 / 256, 1.0])
black = np.array([11 / 256, 11 / 256, 11 / 256, 1.0])
grey = np.array([189 / 256, 189 / 256, 189 / 256, 1.0])
yellow = np.array([255 / 256, 247 / 256, 0 / 256, 1.0])
red = np.array([1.0, 0.0, 0.0, 1.0])
mapping = np.linspace(mesh['values'].min(), mesh['values'].max(), 256)
newcolors = np.empty((256, 4))
newcolors[mapping >= 80] = red
newcolors[mapping < 80] = grey
newcolors[mapping < 55] = yellow
newcolors[mapping < 30] = blue
newcolors[mapping < 1] = black
# Make the colormap from the listed colors
my_colormap = ListedColormap(newcolors)
# %%
# Simply pass the colormap to the plotting routine.
mesh.plot(scalars='values', cmap=my_colormap)
# %%
# Or you could make a simple colormap... any Matplotlib colormap can be passed
# to PyVista.
boring_cmap = plt.get_cmap("viridis", 5)
mesh.plot(scalars='values', cmap=boring_cmap)
# %%
# You can also pass a list of color strings to the color map. This
# approach divides up the colormap into 5 equal parts.
mesh.plot(scalars=mesh['values'], cmap=['black', 'blue', 'yellow', 'grey', 'red'])
# %%
# If you still wish to have control of the separation of values, you
# can do this by creating a scalar array and passing that to the
# plotter along with the colormap
scalars = np.empty(mesh.n_points)
scalars[mesh['values'] >= 80] = 4 # red
scalars[mesh['values'] < 80] = 3 # grey
scalars[mesh['values'] < 55] = 2 # yellow
scalars[mesh['values'] < 30] = 1 # blue
scalars[mesh['values'] < 1] = 0 # black
mesh.plot(scalars=scalars, cmap=['black', 'blue', 'yellow', 'grey', 'red'])
# %%
# Matplotlib vs. Colorcet
# +++++++++++++++++++++++
#
# Let's compare Colorcet's perceptually uniform "fire" colormap to Matplotlib's
# "hot" colormap much like the example on the `first page of Colorcet's docs`_.
#
# .. _first page of Colorcet's docs: https://colorcet.holoviz.org/index.html
#
# The "hot" version washes out detail at the high end, as if the image is
# overexposed, while "fire" makes detail visible throughout the data range.
#
# Please note that in order to use Colorcet's colormaps including "fire", you
# must have Colorcet installed in your Python environment:
# ``pip install colorcet``
p = pv.Plotter(shape=(2, 2), border=False)
p.subplot(0, 0)
p.add_mesh(
mesh,
scalars='Elevation',
cmap="fire",
lighting=True,
scalar_bar_args={'title': "Colorcet Fire"},
)
p.subplot(0, 1)
p.add_mesh(
mesh,
scalars='Elevation',
cmap="fire",
lighting=False,
scalar_bar_args={'title': "Colorcet Fire (No Lighting)"},
)
p.subplot(1, 0)
p.add_mesh(
mesh,
scalars='Elevation',
cmap="hot",
lighting=True,
scalar_bar_args={'title': "Matplotlib Hot"},
)
p.subplot(1, 1)
p.add_mesh(
mesh,
scalars='Elevation',
cmap="hot",
lighting=False,
scalar_bar_args={'title': "Matplotlib Hot (No Lighting)"},
)
p.show()
|