1

Unable to render different colors for specific characters within a LaTeX string

I need to change the color of substrings within a LaTeX string for a plot title. I have tried several different approaches, most of which gave errors and/or warnings. The code below gives no errors or warnings, but does not render the color specified.

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib
matplotlib.use("WXAgg")
import matplotlib.pyplot as plt
plt.rc('text', usetex=True)
plt.rc('text.latex', preamble = r'\usepackage{xcolor}')

N = 50
x = np.random.rand(N)
y = np.random.rand(N)

fig, ax = plt.subplots()
ax.scatter(x, np.cos(x), color = 'blue', marker = "+", s=47.5)
ax.set_title(r'$\color{red}{X}X$') 
#ax.set_title(r"\textcolor{red}{X} $\color{red}{X}$") # does not work either

plt.show()
Birdy40
  • 337
  • 1
  • 6
  • 15
  • I don't think mathtext supports latex color control sequences: https://matplotlib.org/users/mathtext.html – ngoldbaum Feb 04 '19 at 16:05
  • While mathtext does not allow for color, here OP uses `usetex=True`. Still it would only work in certain file formats as shown in [this Q&A](https://stackoverflow.com/questions/9169052/partial-coloring-of-text-in-matplotlib). – ImportanceOfBeingErnest Feb 04 '19 at 16:23
  • Ok, ngoldbaum, I did look at https://matplotlib.org/gallery/text_labels_and_annotations/rainbow_text.html#sphx-glr-gallery-text-labels-and-annotations-rainbow-text-py but I do not believe this actually solves my problem. I need to render colors on an individual character of a LaTeX string. – Birdy40 Feb 04 '19 at 17:10
  • I also looked at https://matplotlib.org/gallery/text_labels_and_annotations/rainbow_text.html#sphx-glr-gallery-text-labels-and-annotations-rainbow-text-py and this looked promising; but, I was unable to get it to work with plt.show() – Birdy40 Feb 04 '19 at 17:16

1 Answers1

1

The easiest way is,

t = ax.set_title("red")
t.set_color("r")

A complete example,

import numpy as np
import matplotlib
matplotlib.use("WXAgg")
import matplotlib.pyplot as plt

plt.rc('text', usetex=True)


N = 50
x = np.random.rand(N)
y = np.random.rand(N)

fig, ax = plt.subplots()
ax.scatter(x, np.cos(x), color = 'blue', marker = "+", s=47.5)
t = ax.set_title(r"X $X$")
t.set_color("r")

plt.show()

UPDATE:

This idea with text can be used to get different colours in a single word, although not an ideal solution as you have to line the various letters up,

t1 = fig.text(0.5,0.9,"$X$", transform=ax.transAxes)
t1.set_color("r")
t2 = fig.text(0.515,0.9,"$X$", transform=ax.transAxes)
t2.set_color("b")

You can make this a function, as in this example adapted for the title,

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker

def multicolor_label(ax, list_of_strings, list_of_colors, anchorpad=0, **kw):
    boxes = [TextArea(text, textprops=dict(color=color, ha='left',va='bottom',**kw)) 
                for text,color in zip(list_of_strings,list_of_colors) ]
    xbox = HPacker(children=boxes,align="center",pad=0, sep=5)
    anchored_xbox = AnchoredOffsetbox(loc=3, child=xbox, pad=anchorpad, frameon=False, 
                                      bbox_to_anchor=(0.5, 1.0), 
                                      bbox_transform=ax.transAxes, borderpad=0.)
    ax.add_artist(anchored_xbox)

plt.rc('text', usetex=True)

N = 50
x = np.random.rand(N)
y = np.random.rand(N)

fig, ax = plt.subplots()
ax.scatter(x, np.cos(x), color = 'blue', marker = "+", s=47.5)
multicolor_label(ax, ["$X$", "$X$"], ["r", "b"])
plt.show()
Ed Smith
  • 12,716
  • 2
  • 43
  • 55
  • Thanks Ed but this actually does not allow control of colors for individual characters in a LaTeX string. For example, in the raw string r"$XX$" I would like the first X to have a different color than the second X. – Birdy40 Feb 04 '19 at 17:41
  • Note, I have tried what I believe to be all the backends possible to render. Unfortunately, this was unsuccessful. – Birdy40 Feb 04 '19 at 17:48
  • And @Ed Smith, I apologize for not being more specific in my original formulation of my problem. I have now given a better (IMHO) description of my problem. – Birdy40 Feb 04 '19 at 18:52
  • Hi @Birdy40, I get a warning saying latex color does not work, I assume this is intentionally not supported as you can achieve colour through matplotlib in other ways. I've added a possible solution which could be adjusted to get close to what you need (although it's pretty hacky). – Ed Smith Feb 05 '19 at 09:05
  • Ok @Ed Smith. Interestingly, I **do not get a warning** that latex color does not work. I am impressed by your _hacky_ solution --- not very elegant, but it does solve my problem. Thanks for your work on this problem. I would like to see a more elegant solution; but, meanwhile I will use this one. – Birdy40 Feb 05 '19 at 11:42
  • @Birdy40, funny, I can't get the error now, was going to post it. Maybe I got it confused with the string of errors about the backends. Did you see this post by the way? Seems to work with `ps`, https://stackoverflow.com/questions/9169052/partial-coloring-of-text-in-matplotlib – Ed Smith Feb 05 '19 at 13:06
  • Yes, I tried the one with `ps` and several variations of it; but, always got errors, when plt.show() executed. However, saving it to a file worked ok! Check your email Ed. – Birdy40 Feb 05 '19 at 18:56