26

When filling a grid with color such as when using contourf in pyplot, I need to find a way to change the color that pyplot uses to fill data that exceed the specified range of the colorbar. I wish to have a static colorbar that does not automatically change its range to fit the max/min of the data, so having occasional extreme values that exceed its bounds is inevitable, and colors need to be specified for such values.

The default color for values exceeding the bounds of the colorbar is white, which can glaringly clash with the surrounding data if the colormap does not have white as its end colors. Example image is shown below - notice the white fill when values exceed the negative range of the colorbar:

enter image description here

I believe there is a way to specify which color to use at each bound if they are exceeded by using rcParams, but I have not been able to find information on this anywhere.

Any help would be appreciated.

Oliver W.
  • 13,169
  • 3
  • 37
  • 50
Levi Cowan
  • 789
  • 2
  • 9
  • 13

1 Answers1

37

The out-of-bounds colors can be set using the set_over and set_under methods of the colormap; see the documentation. You'll need to specify these values when you create your colormap. I don't see any matplotlibrc setting to set the default for this, though. You might also want to ask on the matplotlib mailing list.

Edit: I see what is going on. The white area you describe is not beyond the limits of the color range. It is simply the blank background of the axes. Because you are only plotting certain levels, any levels outside that range will not be plotted at all, leaving those areas blank. To get what you want, do this:

cs = pyplot.contourf(x,y,z,levels=np.arange(50, 220, 20), cmap=pyplot.cm.jet, extend="both")
cs.cmap.set_under('k')
cs.set_clim(50, 210)
cb = pyplot.colorbar(cs)

The "extend" argument is the key; it tells contourf to go ahead and plot all contours, but collapse all outside the given range into "too big" and "too small" categories. The cs.set_clim call is necessary to work around an oddity I discovered in contourf while debugging this; for some reason when you use extend, it manipulates the data limits, so we need to reset them back to what we want them to be.

Also, just as a matter of style, you shouldn't be doing things like Colormap.set_under(cmap,color='k'). This is calling the class method and explicitly passing the instance in, which is an odd way to do it. Just do cmap.set_under(color="k").

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • Ok, but there is an issue when trying to use these methods. Here is a line of code that worked before trying them: `cs = m.contourf(x,y,data,clevs,cmap=pyplot.cm.Spectral)` And here is what I just tried: `cmap=matplotlib.colors.Colormap('Spectral') matplotlib.colors.Colormap.set_under(cmap,color=(0.4667,0,0.5333)) cs = m.contourf(x,y,data,clevs,cmap=cmap)` Which yields this error: `File "/usr/lib/pymodules/python2.7/matplotlib/contour.py", line 943, in _process_colors self.monochrome = self.cmap.monochrome AttributeError: Colormap instance has no attribute 'monochrome' ` – Levi Cowan Jul 08 '12 at 20:42
  • You are instantiating the base Colormap class, creating a new, empty Colormap, not using the "spectral" colormap. The easiest way to do what you want is probably to do `cmap = pyplot.cm.Spectral` and then do `cmap.set_under(...)`. This will modify the Spectral colormap to have the specified under-value. Note that since you are modifying the actual Spectral colormap object, this will remain in effect on all subsequent plots using the Spectral colormap. – BrenBarn Jul 08 '12 at 20:55
  • That makes sense, but employing this did not change the resulting plot, and the "over/under" color is still white. – Levi Cowan Jul 08 '12 at 21:52
  • It's getting too hard to do this in the abstract. You'll need to provide some example code. – BrenBarn Jul 08 '12 at 21:56
  • Here. This script tries to set the "under" color to black instead of white, but values below the lower bound of the colorbar are still white. Sorry don't know how to format multiple lines of code nicely in comments. `from matplotlib import pyplot as plt from numpy import arange,meshgrid from matplotlib.colors import Colormap x,y = arange(-10,10),arange(-10,10) x,y=meshgrid(x,y) z = x**2+y**2 clevs=arange(50,220,20) cmap=plt.cm.jet Colormap.set_under(cmap,color='k') cs = plt.contourf(x,y,z,clevs,cmap=cmap) plt.colorbar(cs) plt.show()` – Levi Cowan Jul 08 '12 at 22:37
  • See my edited reply. The region you describe is not white because white is specified as an "out of range" color. It's white because the background of the plot is white, and you aren't plotting anything at all in that region, because you're only plotting certain levels. – BrenBarn Jul 09 '12 at 00:54
  • Perfect. It works, and I understand the problem now. Thanks a lot for your time. – Levi Cowan Jul 09 '12 at 03:02
  • It works perfectly, but cold we have a rectangle colorbar instead of a double array one ? @BrenBarn – Agape Gal'lo Oct 15 '18 at 16:37
  • @AgapeGal'lo: I don't understand what you mean, and I don't see how that's related to this question. If you have a new questions, please ask it as a separate question on the site. – BrenBarn Oct 15 '18 at 18:00