I have recently switched from making illutrations with TeX (PGF/TikZ) to using Matplotlib for the same purpose. The main reason is that a lot of my scientific code is in python and some of the illustrations should directly use the output of python calculations.
I have been using annotate
and the fancy arrow patch, which already does a lot of what I need, such as drawing curved arrows (see e.g. here). Compared to TikZ, there is one particular thing I have been missing: path decorations (see e.g. https://tex.stackexchange.com/a/193451/96546 for an easy TikZ example). My question is if there is a way to do such TikZ-style path decorations in matplotlib?
Since this is rather broad I will set a particular task (taken from the TeX.SE question https://tex.stackexchange.com/questions/193444/sketching-simple-arrows-with-different-direction): How would I draw the following picture in Matplotlib?
I am aware of this question, but the implementation is not really a decoration of a line between endpoints, but rather a plotted function.
To scale the arrow head in TikZ, we add the option scale=<value> to the square brackets as follows: \draw [-{Stealth[scale=2]}] (0,0) -- (1,0); The result will be an arrow head that is twice of the size of a standard Stealth Arrowhead. We can also scale individual components of length and width.
Another way to change the visual appearance of plots is to set the rcParams in a so-called style sheet and import that style sheet with matplotlib. style. use . In this way you can switch easily between different styles by simply changing the imported style sheet.
I created this in matplotlib with the help of the feynman package by GkAntonius (docs). This has capabilities for neat plotting of various arrow types using vertices and lines, including a style='wiggly'
line style. I also added a straight start and end segment to these wiggly lines, as in the example diagram in the OP. In addition, given the comments/bounty asks for a curved/arch wiggly line, I have also included a demonstration of this functionality.
Code:
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()
Code
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With