You could use make_colormap
to make a custom colormap:
mygreen = make_colormap([c('burnt red'),
c('yellow green'), idx[1], c('yellow green'),
(0,1,0), idx[2], (0,1,0), # RGB (0,1,0) is standard green?
c('dark green')])
The argument to make_colormap
is a sequence of RGB values and floats.
Every float is sandwiched between two RGB values.
The floats indicate locations (on a scale from 0.0 to 1.0) where the color map
transitions from one RGB color to the next.
The first and last values in the sequence are the first and last colors in the
color map.
import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
np.random.seed(2016)
def make_colormap(seq):
"""Return a LinearSegmentedColormap
seq: a sequence of floats and RGB-tuples.
- Every float is sandwiched between two RGB values.
- The floats indicate locations (on a scale from 0.0 to 1.0) where the
color map transitions from one RGB color to the next.
- The floats should be in increasing order
- The first and last values in the sequence are the first and last
colors in the color map.
https://stackoverflow.com/q/16834861/190597 (unutbu)
"""
seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
cdict = {'red': [], 'green': [], 'blue': []}
for i, item in enumerate(seq):
if isinstance(item, float):
r1, g1, b1 = seq[i - 1]
r2, g2, b2 = seq[i + 1]
cdict['red'].append([item, r1, r2])
cdict['green'].append([item, g1, g2])
cdict['blue'].append([item, b1, b2])
return mcolors.LinearSegmentedColormap('CustomMap', cdict)
# There are 103 integers from 0 to 102 (inclusive)
idx = np.linspace(0, 1, 103)
c = mcolors.ColorConverter().to_rgb
mygreen = make_colormap([c('burnt red'),
c('yellow green'), idx[1], c('yellow green'),
(0,1,0), idx[2], (0,1,0), # RGB (0,1,0) is standard green?
c('dark green')])
arr = np.random.randint(0, 103, size=(11, 11))
print(np.where(arr==0))
print(np.where(arr==1))
plt.imshow(arr, interpolation='nearest', cmap=mygreen, vmin=0, vmax=102)
plt.colorbar(ticks=list(range(0, 100, 10))+[102])
plt.show()

Another (probably better) option is to modify arr
to take advantage of matplotlib's
cmap.set_under
and cmap.set_over
methods. These colormap methods allow you to set a color for
all values that go under or over specified limits:
cmap = make_colormap([(0,1,0), c('dark green')])
cmap.set_under('burnt red')
cmap.set_over('yellow green')
Thus, in the special case where you have just two special colors, you could
modify arr
so 0 gets mapped to, say, a negative number, and 1 gets mapped to a
number larger than 100, and shift the rest of the numbers to range from 0 to
100:
arr -= 2
arr = np.where(arr==-1, 102, arr)
For example,
import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
np.random.seed(2016)
def make_colormap(seq):
"""Return a LinearSegmentedColormap
seq: a sequence of floats and RGB-tuples.
- Every float is sandwiched between two RGB values.
- The floats indicate locations (on a scale from 0.0 to 1.0) where the
color map transitions from one RGB color to the next.
- The floats should be in increasing order
- The first and last values in the sequence are the first and last
colors in color map.
https://stackoverflow.com/q/16834861/190597 (unutbu)
"""
seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
cdict = {'red': [], 'green': [], 'blue': []}
for i, item in enumerate(seq):
if isinstance(item, float):
r1, g1, b1 = seq[i - 1]
r2, g2, b2 = seq[i + 1]
cdict['red'].append([item, r1, r2])
cdict['green'].append([item, g1, g2])
cdict['blue'].append([item, b1, b2])
return mcolors.LinearSegmentedColormap('CustomMap', cdict)
c = mcolors.ColorConverter().to_rgb
cmap = make_colormap([(0,1,0), c('dark green')])
cmap.set_under('burnt red')
cmap.set_over('yellow green')
arr = np.random.randint(0, 102, size=(11, 11))
# modify arr so that 0 is mapped to a negative number (-2) and 1 is mapped to a
# positive number greater than 100, (say, 102), and all other values are
# decreased by 2
arr -= 2
arr = np.where(arr==-1, 102, arr)
plt.imshow(arr, interpolation='nearest', cmap=cmap, vmin=0, vmax=100)
plt.colorbar(extend='both')
plt.show()
