Description
Description
I was plotting a colorbar using a custom colormap and levels using ax.colorbar
. However, sometimes I observed that the plot would miss out one level (and its color). After trying with different values I found that when the length of the level is too small, this level would be gone. I tried using values
, norm=DiscreteNorm
and using DiscreteNorm
and DiscreteColormap
, but all these methods failed to make the correct plot.
In the following I will demonstrate this with a colorbar consisting of colors 'blue', 'orange' and 'green', set at levels
As for why I am plotting a colorbar instead of using ScalerMappable
, I am plotting a categorical map using geopandas
. The ScalarMappable
generated cannot be used to add a colorbar, so I have to build it from colors and values.
Steps to reproduce
Method 1: Using values
import proplot as pplt
fig, ax = pplt.subplots()
ax.colorbar(
['blue', 'orange', 'green'],
values=[0, 5, 60, 130],
spacing='proportional',
ticks=10
)
Method 2: Using norm = pplt.DiscreteNorm
import proplot as pplt
fig, ax = pplt.subplots()
ax.colorbar(
['blue', 'orange', 'green'],
norm=pplt.DiscreteNorm([0, 5, 60, 130]),
spacing='proportional',
ticks=10
)
Method 3: Using pplt.DiscreteNorm
and pplt.DiscreteColormap
in cm.ScalarMappable
from matplotlib.cm import ScalarMappable
import proplot as pplt
fig, ax = pplt.subplots()
ax.colorbar(
ScalarMappable(
pplt.DiscreteNorm([0, 5, 60, 130]),
pplt.DiscreteColormap(['blue', 'orange', 'green']),
),
spacing='proportional',
ticks=10
)
Actual behavior:
Method 1
Method 2
Method 3
Equivalent steps in matplotlib
I do not fully use matplotlib
to reproduce. Instead, I can simply use colors.BoundaryNorm
and colors.ListedColormap
to build the ScalarMappable
to obtain the expected hebavior.
import proplot as pplt
from matplotlib import cm, colors
fig, ax = pplt.subplots()
ax.colorbar(
cm.ScalarMappable(
colors.BoundaryNorm([0, 5, 60, 130], ncolors=3),
colors.ListedColormap(['blue', 'orange', 'green']),
),
spacing='proportional',
ticks=10
)
Extra Info
If I reduce the maximum value from 130 to 120, then Method 2 gives the expected plot.
Method 2 (reduced maximum)
import proplot as pplt
fig, ax = pplt.subplots()
ax.colorbar(
['blue', 'orange', 'green'],
norm=pplt.DiscreteNorm([0, 5, 60, 120]),
spacing='proportional',
ticks=10
)
Proplot version
- Matplotlib: 3.4.3
- Proplot: 0.9.5