Matplotlib два разных цвета в одном аннотате

Я пытаюсь создать фигуру на python и сделать так, чтобы один и тот же аннонированный текст имел два цвета, половина аннотации будет синей, а другая половина будет красной.

Я думаю, что код объясняет сам. У меня 3 линии 1 зеленый с зеленым аннонитом, 1 синий с синим аннотация.

Третий красный - это суммирование графика 1 и графика 2, и я хочу, чтобы он имел половину аннотации синего и половины зеленого.

ipython -pylab

x=arange(0,4,0.1)

exp1 = e**(-x/5)
exp2 = e**(-x/1)
exp3 = e**(-x/5) +e**(-x/1) 

figure()
plot(x,exp1)
plot(x,exp2)
plot(x,exp1+exp2)
title('Exponential Decay')


annotate(r'$e^{-x/5}$', xy=(x[10], exp1[10]), xytext=(-20,-35), 
         textcoords='offset points', ha='center', va='bottom',color='blue',
          bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
          arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.95', 
                            color='b'))

annotate(r'$e^{-x/1}$', xy=(x[10], exp2[10]), xytext=(-5,20), 
         textcoords='offset points', ha='center', va='bottom',color='green',
          bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
          arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=-0.5', 
                            color='g'))

annotate(r'$e^{-x/5} + e^{-x/1}$', xy=(x[10], exp2[10]+exp1[10]), xytext=(40,20), 
         textcoords='offset points', ha='center', va='bottom',
          bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
          arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=-0.5', 
                            color='red'))

Возможно ли это?

Ответ 1

Вы можете использовать r'$\textcolor{blue}{e^{-x/5}} + \textcolor{green}{e^{-x/1}}$', чтобы сделать текст наполовину синим, наполовину зеленым. Используя свой собственный код, например:

enter image description here

Изображение генерируется с помощью следующего кода. Тестирование с помощью matplotlib v2.1.2 со стандартными настройками matplotlibrc.

import matplotlib as matplotlib
matplotlib.use('pgf')
matplotlib.rc('pgf', texsystem='pdflatex')  # from running latex -v
preamble = matplotlib.rcParams.setdefault('pgf.preamble', [])
preamble.append(r'\usepackage{color}')

from numpy import *
from matplotlib.pyplot import *

x=arange(0,4,0.1)

exp1 = e**(-x/5)
exp2 = e**(-x/1)
exp3 = e**(-x/5) +e**(-x/1) 

figure()
plot(x,exp1)
plot(x,exp2)
plot(x,exp1+exp2)
title('Exponential Decay')


annotate(r'$e^{-x/5}$', xy=(x[10], exp1[10]), xytext=(-20,-25), 
         textcoords='offset points', ha='center', va='bottom',color='blue',
         bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
         arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.95', 
                            color='b'))

annotate(r'$e^{-x/1}$', xy=(x[10], exp2[10]), xytext=(25,20), 
         textcoords='offset points', ha='center', va='bottom',color='green',
         bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
         arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=-0.5', 
                            color='g'))

annotate(r'$\textcolor{blue}{e^{-x/5}} + \textcolor[rgb]{0.0, 0.5, 0.0}{e^{-x/1}}$', 
         xy=(x[10], exp2[10]+exp1[10]), xytext=(40,20), 
         textcoords='offset points', ha='center', va='bottom',
         bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
         arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=-0.5', 
                            color='red'))

savefig('test.png')

Это в основном ваш код со следующими изменениями:

  1. Вам нужно использовать pgf бэкэнд.
  2. Используйте пакет color в pgf.preamble
  3. Там есть некоторые совпадения с 1-й и 2-й аннотациями, поэтому xytext изменяется.
  4. color='g' во второй аннотации на самом деле не использовал чистый "зеленый" цвет, такой как (0, 255, 0) rgb. \textcolor[rgb]{0.0, 0.5, 0.0} делает его похожим.

Ответ 2

Я не думаю, что вы можете иметь несколько цветов в одной аннотации, поскольку, насколько я знаю, annotate принимает только один текстовый объект в качестве параметра, а текстовые объекты поддерживают только одиночные цвета. Итак, насколько мне известно, нет "родного" или "элегантного" способа автоматического выполнения этого.

Однако существует обходное решение: вы можете иметь несколько текстовых объектов, помещенных произвольно в граф. Итак, вот как я это сделаю:

fig1 = figure()
# all the same until the last "annotate":
annotate(r'$e^{-x/5}$'+r'$e^{-x/1}$', xy=(x[10], exp2[10]+exp1[10]), xytext=(40,20), 
         textcoords='offset points', ha='center', va='bottom',color='white',
          bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
          arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=-0.5', 
                            color='r'))

fig1.text(0.365, 0.62, r'$e^{-x/5}$', ha="center", va="bottom", size="medium",color="blue")
fig1.text(0.412, 0.62, r'$e^{-x/1}$', ha="center", va="bottom", size="medium",color="green")

Что я сделал:

  • Я установил аннотацию color='black';
  • Я создал два текстовых объекта в позициях 0.5, 0.5 (что означает центр fig1);
  • Я вручную изменил позиции до тех пор, пока они не будут грубо перекрываться с черным текстом, сгенерированным annotate (который в итоге оказался значением, которое вы видите в двух вызовах text);
  • Я устанавливаю аннотацию color='white', поэтому она не мешает цвету перекрывающегося текста.

Здесь вывод:

multi-colour annotated graph

Это не очень элегантно, и для его настройки требуется некоторое построение графика, но он выполняет свою работу.

Если вам нужно несколько графиков, возможно, есть способ автоматизировать размещение: если вы не храните объект fig1, координаты для text становятся фактическими координатами x, y на графике, я нахожу, что с чем сложнее работать, но, возможно, это позволит вам автоматически генерировать их, используя координаты аннотации xy? Для меня это не проблема, но если вы это сделаете, я бы хотел увидеть код.