Matplotlib аннотация стрелка с украшением дорожки в стиле TikZ - PullRequest
5 голосов
/ 11 февраля 2020

Я недавно перешел от создания иллюзий с TeX (PGF / TikZ) к использованию Matplotlib для той же цели. Основная причина в том, что большая часть моего научного кода c находится в python, и некоторые иллюстрации должны напрямую использовать результаты расчетов python.

Я использовал annotate и причудливый патч со стрелкой , который уже делает многое из того, что мне нужно, например рисование изогнутых стрелок (см., Например, здесь ). По сравнению с TikZ, я упустил одну особенность: декорации путей (см., Например, https://tex.stackexchange.com/a/193451/96546 для простого примера TikZ). У меня вопрос, есть ли способ сделать такое оформление пути в стиле TikZ в matplotlib?

Поскольку это довольно широкий вопрос, я поставлю определенную задачу (взято из вопроса TeX.SE https://tex.stackexchange.com/questions/193444/sketching-simple-arrows-with-different-direction): Как бы я нарисовал следующую картину в Matplotlib?

enter image description here

Я известно о этом вопросе, но на самом деле реализация - это не украшение линии между конечными точками, а скорее построенная функция.

1 Ответ

3 голосов
/ 18 февраля 2020

Я создал это в matplotlib с помощью пакета feynman от GkAntonius ( docs ). У этого есть возможности для аккуратного построения различных типов стрелок, используя вершины и линии, включая стиль линии style='wiggly'. Я также добавил прямой начальный и конечный сегменты к этим волнистым линиям, как на диаграмме примера в OP. Кроме того, учитывая, что комментарии / щедрость запрашивают изогнутую / изогнутую линию арки, я также включил демонстрацию этой функции.

Диаграмма в вопросе

enter image description here

Код:

import matplotlib.pyplot as plt
from feynman import Diagram

# Set up diagram
fig = plt.figure(figsize=(10.,10.))
ax = fig.add_axes([0,0,1,1], frameon=False)
diagram = Diagram(ax)

# Mirror line
m1 = diagram.vertex(xy=(.1,.5), marker='')
m2 = diagram.vertex(xy=(.9,.5), marker='')
mirror = diagram.line(m1, m2, arrow=False, style='double')


# Top left P-line
p1 = diagram.vertex(xy=(.2, .8), marker='')
p2 = diagram.vertex(xy=(.5, .5), marker='')
P1 = diagram.line(p1, p2, arrow=True, arrow_param={'t':0.91})
P1.text("$P$", fontsize=60, y=-.1, t=.1)


# Bottom right P-line
p3 = diagram.vertex(xy=(.5, .5), marker='')
p4 = diagram.vertex(xy=(.8, .2), marker='')
P2 = diagram.line(p3, p4, arrow=True, arrow_param={'t':0.91})
P2.text("$P$", fontsize=60, y=.05, t=.9)


# Top right P-line
p5 = diagram.vertex(xy=(.5, .5), marker='')
p6 = diagram.vertex(xy=(.8, .8), marker='')
P3 = diagram.line(p5, p6, arrow=True, arrow_param={'t':0.91})
P3.text("$P$", fontsize=60, y=-.05, t=.9)


# Top right SV-line start
sv1_s1 = diagram.vertex(xy=(.5, .5), marker='')
sv1_s2 = diagram.vertex(xy=(.51, .5175), marker='')
SV1_start = diagram.line(sv1_s1, sv1_s2, arrow=False)

# Top right SV-line middle
sv1_1 = diagram.vertex(xy=(.51, .5175), marker='')
sv1_2 = diagram.vertex(xy=(.69, .8325), marker='')
SV1 = diagram.line(sv1_1, sv1_2, arrow=False, style='wiggly', nwiggles=5)
SV1.text("$SV$", fontsize=60, y=.15, t=.9)

# Top right SV-line end
sv1_e1 = diagram.vertex(xy=(.69, .8325), marker='')
sv1_e2 = diagram.vertex(xy=(.7, .85), marker='')
SV1_end = diagram.line(sv1_e1, sv1_e2, arrow=True, arrow_param={'t':0.91})


# Bottom right SV-line start
sv2_s1 = diagram.vertex(xy=(.5, .5), marker='')
sv2_s2 = diagram.vertex(xy=(.51, .4825), marker='')
SV2_start = diagram.line(sv2_s1, sv2_s2, arrow=False)

# Bottom right SV-line middle
sv2_1 = diagram.vertex(xy=(.51, .4825), marker='')
sv2_2 = diagram.vertex(xy=(.69, .1675), marker='')
SV2 = diagram.line(sv2_1, sv2_2, arrow=False, style='wiggly', nwiggles=5)
SV2.text("$SV$", fontsize=60, y=-.15, t=.9)

# Bottom right SV-line end
sv2_e1 = diagram.vertex(xy=(.69, .1675), marker='')
sv2_e2 = diagram.vertex(xy=(.7, .15), marker='')
SV2_end = diagram.line(sv2_e1, sv2_e2, arrow=True, arrow_param={'t':0.91})

diagram.plot()
plt.show()

Изогнутые / арочные линии

enter image description here

код

import matplotlib.pyplot as plt
from feynman import Diagram

# Set up diagram
fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0,0,1,1], frameon=False)
diagram = Diagram(ax)

# Curvy wiggly line
sv1_1 = diagram.vertex(xy=(.205, .205), marker='')
sv1_2 = diagram.vertex(xy=(.79, .79), marker='')
SV1 = diagram.line(sv1_1, sv1_2, arrow=False, style='wiggly elliptic ', nwiggles=8)
SV1.text("$1$", fontsize=50, y=.15, t=.5)

# Curvy wiggly line end
sv1_e1 = diagram.vertex(xy=(.79, .79), marker='')
sv1_e2 = diagram.vertex(xy=(.8, .8), marker='')
SV1_end = diagram.line(sv1_e1, sv1_e2, arrow=True, arrow_param={'t':0.91})


# Circular wiggly line
sv2_1 = diagram.vertex(xy=(.75, .25), marker='')
SV2 = diagram.line(sv2_1, sv2_1, arrow=False, style='wiggly circular', nwiggles=8)
SV2.text("$2$", fontsize=50, y=.15, t=.5)

diagram.plot()
plt.show()
...