Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial coloring of text in matplotlib

Is there a way in matplotlib to partially specify the color of a string?

Example:

plt.ylabel("Today is cloudy.")

How can I show "today" as red, "is" as green and "cloudy." as blue?

like image 735
Gökhan Sever Avatar asked Feb 06 '12 23:02

Gökhan Sever


3 Answers

I only know how to do this non-interactively, and even then only with the 'PS' backend.

To do this, I would use Latex to format the text. Then I would include the 'color' package, and set your colors as you wish.

Here is an example of doing this:

import matplotlib
matplotlib.use('ps')
from matplotlib import rc

rc('text',usetex=True)
rc('text.latex', preamble='\usepackage{color}')
import matplotlib.pyplot as plt

plt.figure()
plt.ylabel(r'\textcolor{red}{Today} '+
           r'\textcolor{green}{is} '+
           r'\textcolor{blue}{cloudy.}')
plt.savefig('test.ps')

This results in (converted from ps to png using ImageMagick, so I could post it here): enter image description here

like image 123
Yann Avatar answered Nov 12 '22 21:11

Yann


Here's the interactive version. Edit: Fixed bug producing extra spaces in Matplotlib 3.

import matplotlib.pyplot as plt
from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):
    """
    Take a list of strings ``ls`` and colors ``lc`` and place them next to each
    other, with text ls[i] being shown in color lc[i].

    This example shows how to do both vertical and horizontal text, and will
    pass all keyword arguments to plt.text, so you can set the font size,
    family, etc.
    """
    t = plt.gca().transData
    fig = plt.gcf()
    plt.show()

    #horizontal version
    for s,c in zip(ls,lc):
        text = plt.text(x,y,s+" ",color=c, transform=t, **kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, x=ex.width, units='dots')

    #vertical version
    for s,c in zip(ls,lc):
        text = plt.text(x,y,s+" ",color=c, transform=t,
                rotation=90,va='bottom',ha='center',**kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, y=ex.height, units='dots')


plt.figure()
rainbow_text(0.05,0.05,"all unicorns poop rainbows ! ! !".split(), 
        ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
        size=20)

enter image description here

like image 34
Paul Ivanov Avatar answered Nov 12 '22 19:11

Paul Ivanov


Extending Yann's answer, LaTeX coloring now also works with PDF export:

import matplotlib
from matplotlib.backends.backend_pgf import FigureCanvasPgf
matplotlib.backend_bases.register_backend('pdf', FigureCanvasPgf)

import matplotlib.pyplot as plt

pgf_with_latex = {
    "text.usetex": True,            # use LaTeX to write all text
    "pgf.rcfonts": False,           # Ignore Matplotlibrc
    "pgf.preamble": [
        r'\usepackage{color}'     # xcolor for colours
    ]
}
matplotlib.rcParams.update(pgf_with_latex)

plt.figure()
plt.ylabel(r'\textcolor{red}{Today} '+
           r'\textcolor{green}{is} '+
           r'\textcolor{blue}{cloudy.}')
plt.savefig("test.pdf")

Note that this python script sometimes fails with Undefined control sequence errors in the first attempt. Running it again is then successful.

like image 11
Felix Avatar answered Nov 12 '22 20:11

Felix