Рисование текста на границе другого текстового объекта в Matplotlib - PullRequest
0 голосов
/ 31 марта 2012

Я пытаюсь создать текстовые метки на графике в Matplotlib, и я хотел бы выделить некоторые слова, используя другой цвет.Поскольку Matplotlib не имеет встроенной функции для этого, я полагаю, что мог бы расположить два текстовых элемента рядом друг с другом, но у меня возникли проблемы с выравниванием их должным образом. для запроса соответствующей функции, и пример выходных данных ниже - это то, что я хочу эмулировать, но я не могу скопировать его, даже если я скопирую использованный им код и сохраню его в PNG ( это то, что я получаю).Изменил ли Matplotlib то, как его API обрабатывает перевод или получение границ текста?

Как мне это сделать?Любое руководство приветствуется.

Ответы [ 2 ]

1 голос
/ 31 марта 2012

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

импорт matplotlib.pyplot как plt из 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()

    #### note: this line moved down ....### 
    #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')

    t = plt.gca().transData
    fig = plt.gcf()
    plt.show() ############### when this is here, you can see that 
               ############### all unicorns poo rainbows ;-)

plt.figure()

rainbow_text(0.0,0.0,"all unicorns poop rainbows ! ! !".split(), 
        ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
        size=30)
### worked on matplotlib version 1.1.0 on Debian Wheezy. Which version did you try?
0 голосов
/ 30 октября 2013

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

Этот пример является модификацией вашего кода, которая допускает любое вращение текста на угол. Однако это работает только для текста va='bottom' и ha='left'.

import math
import numpy

from numpy.linalg import inv
from matplotlib import transforms
from matplotlib import pyplot as plt

def rainbow_text(x, y, ls, lc, theta, **kwargs):
    fig = plt.gcf()
    axis = plt.gca()

    theta_rad = math.radians(theta)
    text_trans = axis.transData
    for s, c in zip(ls, lc):
        text = plt.text(x, y, " %s " %s,
                        verticalalignment='bottom',
                        horizontalalignment='left',
                        color=c,
                        transform=text_trans,
                        rotation=theta,
                        **kwargs)

        text.draw(axis.figure.canvas.get_renderer())

        # solve for the text width and height
        bbox = text.get_window_extent(axis.figure.canvas.get_renderer())
        theta_mat = numpy.array([[math.cos(theta_rad), math.sin(theta_rad)],
                                 [math.sin(theta_rad), math.cos(theta_rad)]])
        txt_size = numpy.dot(inv(theta_mat),
                             numpy.array([bbox.width, bbox.height]))

        # plot the bounds for each word (only works with axis autoscaling off)
        for i in range(4):
            bounds = bbox.corners()
            point = axis.transData.inverted().transform(bounds[i])
            plt.plot(point[0], point[1], '*', color=c)

        x_offset = txt_size[0] * math.cos(theta_rad)
        y_offset = txt_size[0] * math.sin(theta_rad)
        text_trans = transforms.offset_copy(text.get_transform(),
                                            fig=fig,
                                            x=x_offset,
                                            y=y_offset,
                                            units='points')


plt.figure()
plt.axis([0, 5, 0, 5])

rainbow_text(1, 1, "all unicorns poop rainbows ! ! !".split(),
             ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
             20, size=20)
plt.savefig('blarg.png', ext='png')
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...