Question

[Solved] Matplotlib ScalarMappable: why need to set_array() if norm set?

I’m trying to plot a set of polygons with a colormap. I set up a ScalarMappable object and generate polygon colors from that ScalarMappable, but when I try to add a colorbar, I get the error:

TypeError: You must first set_array for mappable

The documentation for “set_array” doesn’t really say anything, so I’m not at all clear what it is doing, whether I need to give it values, and if I do, what they will be doing.

Can anyone please explain what set_array does, and how I should deal with this?

    plt.clf()
    fig, ax  = plt.subplots(1,1)

    # Set color mappable
    range_min = df.col1.min()
    range_max = df.col1.max()
    cmap = matplotlib.cm.ScalarMappable(
          norm = mcolors.Normalize(range_min, range_max), 
          cmap = plt.get_cmap('binary'))

    for i in polygonDict.keys():
        ax.add_patch(ds.PolygonPatch(polygonDict[i], fc = cmap.to_rgba(df.col1.loc[i])))

    fig.colorbar(cmap, ax = ax)
Solution #1:

A far easier way to do this is to send an empty array [] to set_array().
I don’t really know why, but I’ve seen it done in this answer, and it works.

The only thing I know is that before you set the array, you get None from get_array(), which is probably why you get this error.

You can do :

plt.clf()
fig, ax  = plt.subplots(1,1)

# Set color mappable
range_min = df.col1.min()
range_max = df.col1.max()
cmap = matplotlib.cm.ScalarMappable(
      norm = mcolors.Normalize(range_min, range_max), 
      cmap = plt.get_cmap('binary'))

for i in polygonDict.keys():
    ax.add_patch(ds.PolygonPatch(polygonDict[i], fc = cmap.to_rgba(df.col1.loc[i])))

cmap.set_array([]) # or alternatively cmap._A = []

fig.colorbar(cmap, ax = ax)

After a few tests, it seems that you can send any array in the world ([df.col1], [0,1], [‘hello’]) to set_array(), and your colorbar will be the one you want. It just can’t be None.

I’ve noticed that if you set the array to an number array, and then call autoscale(), the min and max values of the colorbar will be the min and max of that array.

I hope this helps.

Respondent: matthieu
Solution #2:

This may be too late, but I bumped into the same problem today.

So far as I understand it, imshow() and scatter() create a mappable object to convert from a floating point value to a colour in a two step process.

First the floating point number is mapped to the range 0..1, then the the appropriate RGB for that normalised number is looked up in the colour map.

Artists such as PolygonPatch don’t create this mappable, so you need to do it yourself using ColorbarBase()

Here’s what I ended up doing.

def createColourbar(lwr, upr):
    """Create a colourbar with limits of lwr and upr"""
    cax, kw = matplotlib.colorbar.make_axes(mp.gca())
    norm = matplotlib.colors.Normalize(vmin = lwr, vmax = upr, clip = False)

    c = matplotlib.colorbar.ColorbarBase(cax, cmap=mp.spectral(), norm=norm)
    return c
Respondent: Fergal
Solution #3:

This seems to have been fixed in matplotlib v3.1.0 (was not working in v3.0.2).

Respondent: chris.currin
The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Most Popular

To Top
India and Pakistan’s steroid-soaked rhetoric over Kashmir will come back to haunt them both clenbuterol australia bossier man pleads guilty for leadership role in anabolic steriod distribution conspiracy