weird behaviour in ScalarMappable with ListedColormap

Hi.

i am using ListedColormap with ScalarMappable, to map data ranges, without using a norm. But i dont know if what i am doing is a good thing or not.

Here’s the snippet:

···

from matplotlib import pyplot as plt
from matplotlib import colors, cm

cl = ["#8080FF", #purple
#40C0FF”, #blue
#00FFFF”, #cyan
#00FF00”, #green
#FFFF00”, #yellow

  "#FF8000", #orange
  "#FF0000"] #red

cmap = colors.ListedColormap(cl)

data = np.array([np.arange(0, 5, 10, 15, 20, 25, 30, 35, 40, 45)])

sm = cm.ScalarMappable(cmap=cmap)
sm.set_clim(vmin=5, vmax=40) #7 colors, max-min=35

rgba = sm.to_rgba(data, bytes=True)

plt.imshow(rgba, interpolation=“nearest”)
plt.show()

this produces output (first letters of color list):

“p, p, b, c, g, y, o, r, r, r”
as i intend.

5<=val<10 --> purple,
10<=val<15 --> blue

15<=val<20 -->cyan

…etc

BUT, when the color list is much longer than here, where each specific color corresponds to some data range, somehow, sometimes the above doesn’t work as expected.

for example, 15<=val<20 --> should be cyan. but in lists with much more color numbers, value=15 sometimes produces blue. by trial & error, i saw only when an epsilon is added to 15, say 15.000001, data color becomes cyan.

i reckon this has something to do with color number. when the number of colors in ListedColormap is not an integer power of 2 (8, 16, 32, 64…etc) the normalization in set_clim divides 0-1 into sections, which are not exactly representable in machine float, if the color number is, say, 12, 17, 20…etc. so this small differences in color-change-limits result this behaviour. so adding one extra dummy color can solve this, as it completes color number to 8 (2^3 colors).

is this the case or is my guess is completely wrong ?

secondly, i also would like to know the logic behind how matplotlib corresponds/maps values in whole range like i use above, with colors in color list. i digged the source but no success. say 4 colors in list and set_clim(vmin=2, vmax=4).

this yields for values:

below 2 ->color1

2-(2.5) ->color1

2.5-(3) ->color2

3-(3.5) ->color3

3.5 and above ->color4. but how ?

thanks.


Yasin
“Bismillah, her hayrın başıdır.”