Search code examples
pythonmatplotlibhslseaborn

seaborn husl or hsl color palette is not working: remains default black and white colors


I am in need of a circular colormap, and came across this answer which describes using seaborn to import the husl system. I am trying to replicate the simple usage the example demonstrates, but I can't get my image to show up in color. It always displays in black and white (seaborn default color palette). I am working in ipython, but not in the ipython notebook. (Some seaborn functions work only in ipython notebook -- I need an answer that does not rely on that.) Specifically python 2.7.3, ipython 1.1.0.

MWE:

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

fig = plt.figure()

im = np.random.random((100, 100))
with sns.color_palette("husl", 8):
    plt.imshow(im)

Displays:

https://i.sstatic.net/ahKAH.jpg


Solution

  • The other answer is (close to) the right solution, but it might be helpful to understand why this is happening. sns.set_palette and using sns.color_palette in a with statement control the matplotlib color cycle, (mpl.rcParams["axes.color_cycle"]), which is used to style plot elements when using plt.plot.

    In contrast,imshow has a default colormap, which is both a different kind of object (one is a list of colors, the other is a continuous mapping from a scalar variable to a color) and has a different default setting (mpl.rcParams["image.cmap"]).

    As @cphlewis notes, you can use the list of colors returned by sns.color_palette to make a colormap object, but I wouldn't do it quite that way. You can see why if you add a colorbar to the plot:

    import numpy as np
    from scipy.ndimage import gaussian_filter
    import seaborn as sns
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    sns.set_style("dark")
    
    img = np.random.normal(size=(100, 100))
    img = gaussian_filter(img, 3, 2)
    
    cmap1 = mpl.colors.ListedColormap(sns.color_palette("husl"))
    
    plt.figure()
    plt.imshow(img, cmap=cmap1)
    plt.colorbar()
    

    enter image description here

    Here's you're just making a colormap with 6 unique values, which will cause you to lose a lot of high-frequency information in the data. It's better to use more colors; 256 is a good number:

    cmap2 = mpl.colors.ListedColormap(sns.color_palette("husl", 256))
    
    plt.figure()
    plt.imshow(img, cmap=cmap2)
    plt.colorbar()
    

    enter image description here

    You may also want to use the sns.husl_palette function directly so you can control where the cycle starts and what level is used for lightness and saturation:

    cmap3 = mpl.colors.ListedColormap(sns.husl_palette(256, .33, .85, .6))
    
    plt.figure()
    plt.imshow(img, cmap=cmap3)
    plt.colorbar()
    

    enter image description here