Вращение легенды или добавление патча к метке оси в matplotlib

У меня есть необычный сценарий использования matplotlib, который я пытаюсь решить. У меня есть пара осей, созданных с помощьюtwinx(), Каждый содержит ровно один линейный объект с разными стилями. Вместо того, чтобы иметь обычную легенду, я должен добавить патч, который представляет каждую линию к метке y каждой оси. Вот что я пытаюсь достичь:

В идеале, патч должен быть выше текста, но это очень незначительная деталь по сравнению с достижением желаемого результата.

Я попытался два подхода к этой проблеме, оба из которых закончились неудачей. Возможно, гуру матплотлиб может помочь:

# 1: Использование смещенных легенд

from matplotlib import pyplot as plt
fig = plt.figure()
ax = fig.subplots(111)
ax = fig.add_subplot(111)
ax2 = ax.twinx()
l1, = ax.plot((0, 1), (1, 0), linestyle='-', color='blue')
l2, = ax.plot((0, 1), (0, 1), linestyle='--', color='red')
leg1 = ax.legend([l1], ['Solid Blue Line'], bbox_to_anchor=(-0.102, 0., 0.102, 1.), frameon=False, mode='expand', loc=4)
leg2 = ax2.legend([l2], ['Dashed Red Line'], bbox_to_anchor=(1.102, 0., 0.102, 1.), frameon=False, mode='expand', loc=3)

Как и ожидалось, это правильно размещает легенды, но не вращает их. Я не могу выполнить вращение, потому что, по-видимому, легенды не могут вращаться, несмотря наArtist расширения. Например.,leg1.set_transform(leg1.get_transform() + Affine2D().rotate_deg(-90)) не делает ничего, чтобы изменить угол легенды:

# 2 Использование собственного AnchoredOffsetBox

При таком подходе я попытался создать собственное поле, содержащее текст и патч. К сожалению, патч не отображается должным образом.

from matplotlib import pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, DrawingArea, HPacker
from matplotlib.transform import Affine2D

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1, 2, 3], [0, 3, -1], color='g', linestyle='solid')
textArea = TextArea('This is an x-label')
drawArea = DrawingArea(1., 1.)
patch = Line2D((0, 1), (0, 1), color='g', linestyle='solid')
drawArea.add_artist(patch)
content = HPacker(children=[textArea, drawArea], align="center", pad=0, sep=5)
label = AnchoredOffsetbox(loc=10, child=content, pad=0, bbox_to_anchor=(0.5, -0.1), bbox_transform=ax.transAxes, frameon=False)
ax.add_artist(label)
label.set_transform(label.get_transform() + Affine2D().rotate_deg(-90))

Опять вращение вообще не работает. Кроме того, патч не масштабируется разумно, как это было бы в записи легенды (обратите внимание на крошечную зеленую точку в конце метки):

Можно ли добиться чего-то похожего на результат, которого я желаю в MatPlotLib? Я готов вникать в исходный код и, возможно, представить PR, если он поможет, но у меня нет четкого представления о том, с чего начать.

ОБНОВИТЬ

Глядя на исходный код,set_transform методыmatplotlib.offsetbox.TextArea а такжеmatplotlib.offsetbox.DrawingArea полностью игнорируются. Это означает, что моя вторая попытка была бы бессмысленной, даже если бы я заставил патч правильно рисовать.

 bmello21 нояб. 2017 г., 19:39
Я разместил ответ на другой вопрос, который может решить вашу проблему. Пожалуйста, проверьте:stackoverflow.com/a/47317114/3482418.

Ответы на вопрос(1)

Решение Вопроса

которое позволяет избежать кошмарных попыток выстроить боксы вне осей, является использование латексных меток сtextcolor, Следующий код

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

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
l1, = ax.plot((0, 1), (1, 0), linestyle='-', color='blue')
l2, = ax.plot((0, 1), (0, 1), linestyle='--', color='red')

ax.set_ylabel(r'\textcolor{blue}{--}' + r'$\;$ Solid Blue Line')
ax2.set_ylabel(r'\textcolor{red}{- -}' + r'$\;$ Dashed Red Line')

#may need to convert test.ps -trim test.png for picture
plt.savefig('test.ps')

результаты в тестовом файле, который выглядит так,

Латекс позволяет использовать \ hline для разработки линий (или добавить\n \usepackage{dashrule} к преамбуле), \ круг и т. д. для маркеров, цветов по вашему выбору, и вы можете управлять пробелами с\;

ОБНОВЛЕНИЕ: еще несколько примеров стилей маркеров, цветов и линий,

import matplotlib
matplotlib.use('ps')
from matplotlib import rc
rc('text',usetex=True)
latex_pream = matplotlib.rcParams['text.latex.preamble']
latex_pream.append(r'\usepackage{color}')
latex_pream.append(r"\definecolor{lllgrey}{rgb}{0.9,0.9,0.9}")
latex_pream.append(r"\definecolor{lightblue}{rgb}{0.56485968018118948, 0.7663975529283894, 0.86758939636894861}")
latex_pream.append(r"\newcommand*{\xlinethick}[1][1.0em]{\rule[0.4ex]{#1}{1.5pt}}")
latex_pream.append(r"\newcommand*{\xdashthick}[1][1.0em]{\rule[0.5ex]{2.5pt}{1.5pt} $\!$ \rule[0.5ex]{2.5pt}{1.5pt}}")

import matplotlib.pyplot as plt

plt.text(0.1,0.5,"Latex marker and line examples: \n $\;\;\;\;\;$ \{" 
          + r'\textcolor{blue}{$ - - \!\!\!\!\!\!\!\! \bullet \;$} ' + ',$\;\;

что приводит к

+ r'\textcolor{red}{$\bullet$} $\!\!\!\!\! \:\! \circ

что приводит к

+ ',$\;\;

что приводит к

+ r'\textcolor{lllgrey}{\xlinethick}' + ',$\;\;

что приводит к

+ r'\textcolor{lightblue}{\xdashthick}' + ' \}', fontsize=24) #may need to convert test.ps -trim test.png for picture plt.savefig('test.ps')

что приводит к

 Mad Physicist30 июн. 2016 г., 23:15
Для чего нужны знаки доллара?
 Mad Physicist27 июн. 2016 г., 17:41
Я подумываю о том, чтобы написать небольшой пакет, который делает какие-то необычные вещи с преамбулой в rc и в основном добавляет «легенды» LaTeX к меткам рисунков. Могу представить это как пиар, если это кажется стоящим.
 Ed Smith11 июл. 2016 г., 09:55
Я думаю, что да. Я получил код цвета латекса отstackoverflow.com/questions/9169052/... который предполагает, что это работает только с бэкэндом PS ...
 Ed Smith01 июл. 2016 г., 09:00
Они обозначают линейные уравнения в латексе, они нужны вам для чего угодно с обратной косой чертой, например\bullet \circ и по какой-то причине интервал (;, \! и т.д.) не работает в интерпретаторе латекса matplotlib без них.
 Mad Physicist24 июн. 2016 г., 23:00
Теперь, когда я попробовал это и автоматизировал часть, которая связывает стиль / цвет линии с латексным кодом, я хотел бы еще немного поднять это.
 Mad Physicist08 июл. 2016 г., 21:10
Сколькоmatplotlib.use('ps') необходимо здесь? У меня возникли проблемы с отображением цветов в бэкэнде по умолчанию.
 Mad Physicist01 июл. 2016 г., 15:31
Благодарю. Я используюdashrule Пакет пытается получить хотя бы стили линий, представленные в общем случае. Столкнулся сЭта проблематак что может потребоваться немного больше работы, чем просто придумать латексный код, чтобы этот пакет заработал.
 Mad Physicist27 июн. 2016 г., 21:21
Кроме того, просто хотел отметить, что преамбула обычно представляет собой список, а не одну строку. Вы можете просто сделатьmatplotlib.rcParams['text.latex.preamble'].append(r'\usepackage{color}'), так далее.
 Mad Physicist11 июл. 2016 г., 15:49
Облом. Мне бы очень хотелось это в интерактивном режиме.
 Mad Physicist24 июн. 2016 г., 16:50
Кроме того, есть ли конкретная причина, по которой вы написалиr'\textcolor{red}{- -}' + r'$\;$ Dashed Red Line' вместоr'\textcolor{red}{- -}$\;$ Dashed Red Line'?
 Mad Physicist24 июн. 2016 г., 16:33
Это имеет большое значение для решения моей проблемы. Для каждого случая использования, с которым я столкнулся, это работает отлично. Единственная потенциальная проблема заключается в том, что если я когда-либо буду использовать маркеры, будет трудно реализовать все функции маркеров в латексе.
 Ed Smith28 июн. 2016 г., 10:07
Пакет легенды звучит как хорошая идея. Спасибо за совет по добавлению, я не знал, что вы могли бы сделать это, но позволяет вам что-нибудь добавить, я обновил ответ выше с несколькими примерами маркеров, которые я получил из различных латексных файлов.
 Ed Smith27 июн. 2016 г., 11:09
это здорово, что это сработало для тебя. У меня были проблемы с латексным переводчиком$\;$ из оставшейся строки. Вы можете получить самые простые маркеры в латексе, такие как пустые формы с"$\square,\circ,\triangle$", Линии с заполненными маркерами-o- может быть реализовано с чем-то вроде(\textcolor{blue}{$ - - \!\!\!\!\!\!\!\! \bullet \;$ }) и круги с очертаниями\textcolor{red}{$\bullet$} \!\!\!\!\!\!\! $\circ$, С hline в различных пунктирных формах, я думаю, это все, что мне нужно

Ваш ответ на вопрос