Simple steps to create custom colormaps in Python

Creating any colormap at your wills

Guangyuan(Frank) Li
Towards Data Science

--

Photo by Pawel Czerwinski on Unsplash

Imagine you find a pretty colormap that other people used in their publications, and you want to use that in your results as well. However, unfortunately, it is not a built-in colormap in matplotlib. Is there a solution around?

So today I am going to show you how I usually resolve this problem by creating my custom colormap based on any image.

The Github repository for the wrapper function can be found at: https://github.com/frankligy/scTriangulate/blob/main/image/colors_module/README.md

I encountered a nice-looking colormap in this Cell Paper, in their figure4, panel K, there’s a rainbow-like colormap that shows great contrasts and is also visually attractive. The first step we need to do is to take a screenshot of this colormap, shown below:

The example colormap we want to create (Image by Author)

As you can see, it seems that it has 5 different color patches within each of them within which there’s also a gradient. To reproduce this colormap in python, we first need to know the colors of some of the anchor points, the more anchor points we supply, the closer our colormap will look toward the original one. To extract the color of anchor points, we used the free web app adobe color gradient.

After uploading the screenshots, we extracted the RGB values of 6 anchor points (Image by Author)

The app asks us to upload the screenshot and then you can extract the RGB color (represented as the values from 0–255) for the arbitrary number of anchor points. Here we chose 6 because we assume there are 5 different color patches.

The RGB values I highlighted in the red box will help us to create the custom colormaps in the next steps.

The logic of building a custom colormap in matplotlib is a little bit confusing at the first glance, it requires us to first create a cdict dictionary with the specification of red , green and blue channels’ dynamic changes. Using a simpler example to explain the syntax:

Understanding the syntax of cdict (Image by Author)

As in the above example, we instructed the program how to linearly interpolate the R, G, and B channels on the continuum from 0 to 1. The key concept is to select breakpoints at which we express the intensity of the color channels. Another confusing point is that there are two values we need to put, one is the intensity left to the breakpoint whereas the other one is the intensity to the right. In a simple situation like the example I just showed, it is totally fine to use the same intensity for both left and right. For more detailed manipulation, we can make them different for the desirable effects. With that in mind, we can finally start our journey!

Step1 is to install and load necessary packages:

from matplotlib import colors
import numpy as np
import os
import matplotlib.pyplot as plt
from matplotlib import cm

We first build the cdict as illustrated above, here we define a function inter_from_256() to convert Adobe output values (0–255) to range (0,1).

def inter_from_256(x):
return np.interp(x=x,xp=[0,255],fp=[0,1])

Now the custom colormap object can be instantiated:

new_cmap = colors.LinearSegmentedColormap('new_cmap',segmentdata=cdict)

We can test it by generating a color bar using our custom colormap:

fig,ax = plt.subplots()
fig.colorbar(cm.ScalarMappable(norm=colors.Normalize(),cmap=new_cmap),ax=ax)
Our custom color map (Image by Author)

One-line code for the whole process?

When I first encountered this problem a few months ago, I found repeating this process several times for new colormaps is a pain. So I started to write a module called “colors” in one of my developed python packages called scTriangulate. Let’s use the very handy function build_custom_continuous_cmap in the colors module to simplify the whole process down to one line of code:

As you can see, we just need to pass all the RGB values in the adobe web app to the function and don’t need to worry about the underlying processes anymore.

Now we test it again:

fig,ax = plt.subplots()
fig.colorbar(cm.ScalarMappable(norm=colors.Normalize(),cmap=new_cmap),ax=ax)
The same results can be obtained (Image by Author)

Conclusion

Here’s the end, I hope you found this short tutorial helpful in your situations. Also, I’d like to refer you to the scTriangulate.colors modules for more convenient functions for python visualization. Part of the reason I wrote this tutorial is also to get your valuable feedback on what other tedious plotting processes in python that you hope to simplify? If you have any feature requests, please let me know so I can implement them and add them to the scTriangulate.colors modules to benefit other users.

That’s about it! I hope you find this article interesting and useful, thanks for reading! If you like this article, follow me on medium, thank you so much for your support. Connect me on my Twitter or LinkedIn, also please let me know if you have any questions or what kind of tutorials you would like to see In the future!

--

--