Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: Color bar on contour without striping

In matplotlib, I'm looking to create an inset color bar to show the scale of my contour plot, but when I create the contour using contour, the color bar has white stripes running through it, whereas when I use contourf, the colorbar has the proper "smooth" appearance:

Contour comparisons

How can I get that nice smooth colorbar from the filled contour on my normal contour plot? I'd also be OK with a filled contour where the zero-level can be set to white, I imagine.

Here is code to generate this example:

from numpy import linspace, outer, exp
from matplotlib.pyplot import figure, gca, clf, subplots_adjust, subplot
from matplotlib.pyplot import contour, contourf, colorbar, xlim, ylim, title
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

# Make some data to plot - 2D gaussians
x = linspace(0, 5, 100)
y = linspace(0, 5, 100)
g1 = exp(-((x-0.75)/0.2)**2)
g2 = exp(-((y-4.25)/0.1)**2)
g3 = exp(-((x-3.5)/0.15)**2)
g4 = exp(-((y-1.75)/0.05)**2)
z = outer(g1, g2) + outer(g3, g4) 

figure(1, figsize=(13,6.5))
clf()

# Create a contour and a contourf
for ii in range(0, 2):
    subplot(1, 2, ii+1)

    if ii == 0:
        ca = contour(x, y, z, 125)
        title('Contour')
    else:
        ca = contourf(x, y, z, 125)
        title('Filled Contour')

    xlim(0, 5)
    ylim(0, 5)

    # Make the axis labels
    yt = text(-0.35, 2.55, 'y (units)', rotation='vertical', size=14);
    xt = text(2.45, -0.4, 'x (units)', rotation='horizontal', size=14)

    # Add color bar
    ains = inset_axes(gca(), width='5%', height='60%', loc=2)
    colorbar(ca, cax=ains, orientation='vertical', ticks=[round(xx*10.0)/10.0 for xx in linspace(0, 1)])

    if ii ==1:
        ains.tick_params(axis='y', colors='#CCCCCC') 

subplots_adjust(left=0.05, bottom=0.09, right=0.98, top=0.94, wspace=0.12, hspace=0.2)

show()

Edit: I realize now that at the lower resolution, the white striping behavior is hard to distinguish from some light transparency. Here's an example with only 30 contour lines which makes the problem more obvious:

FewContours

Edit 2: While I am still interested in figuring out how to do this in the general general case (like if there's negative values), in my specific case, I have determined that I can effectively create something that looks like what I want by simply setting the levels of a filled contour to start above the zero-level:

ca = contourf(x, y, z, levels=linspace(0.05, 1, 125))

Which basically looks like what I want:

KlugeContours

like image 554
Paul Avatar asked Nov 03 '13 02:11

Paul


1 Answers

A simple hack is to set the thickness of the lines in the colorbar to some higher value. E.g. storing the colorbar object as cb and adding the following lines to your example

for line in cb.lines: 
   line.set_linewidth(3)

gives enter image description here

like image 200
Jakob Avatar answered Oct 05 '22 07:10

Jakob