I was wondering for the purpose of key argument mutational_scale in matplotlib; in the case of matplotlib.patches.FancyArrowPatch which is used to plot an arrow, mutational_scale is set to 1 by default. From the docs:
scalar, optional (default: 1)
Value with which attributes of arrowstyle (e.g., head_length) will be scaled.
When I plot an arrow between two scatter points of size 300, like this:
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots()
ax.scatter([0,1],[0,1], s=300)
arrow = mpl.patches.FancyArrowPatch((0,0), (1,1), arrowstyle='-|>')
plt.show()
The arrow head is non-visible.

However, when I use:
arrow = mpl.patches.FancyArrowPatch((0,0), (1,1), arrowstyle='-|>', mutational_aspect=20)
I get the proper arrow.

My guess is that the overall figure is scaled by a factor larger than 1, closer to 20, making the arrow head invisible with a mutational scale of 1 but visible when using 20. But it's just a guess.
If so, is there a way to know the mutation scaling of the overall figure to decide the proper scaling value for the arrow head?
In the annotating-with-arrow subsection
in the documentation the arrowstyle parameters are presented. For the -|> style it says
-|>head_length=0.4,head_width=0.2
This means that the head of the arrow is 0.4*mutation_scale long and 2*0.2*mutation_scale wide. The units are points.
Since FancyArrowPatches are designed to be used with annotations, the mutation scale would be set to the fontsize in points when drawing an annotation. E.g. for a 15 pt fontsize, mutation_scale=15.
When using a FancyArrowPatch on it's own one hence set the desired size in points
arrow = mpl.patches.FancyArrowPatch((0,1), (1,1), arrowstyle='-|>', mutation_scale=15)
This will create an arrow with full arrow head width 2*0.2*15=6 points.
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots(dpi=100)
ax.set_xlim([-0.6,5])
for i in [5,10,15,20,25]:
ax.scatter([0,1],[i,i], s=(2*.2*i)**2)
arrow = mpl.patches.FancyArrowPatch((0,i), (1,i), arrowstyle='-|>',
mutation_scale=i)
ax.add_patch(arrow)
ax.text(1.2,i,"mutation_scale = {}".format(i),
va="center")
plt.show()

Alternatively, you can specify the head_length and head_width in points directly,
arrow = mpl.patches.FancyArrowPatch((0,1), (1,1),
arrowstyle='-|>,head_width=3,head_length=6')
The following would hence produce the same image as above:
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots(dpi=100)
ax.set_xlim([-0.6,5])
for i in [5,10,15,20,25]:
ax.scatter([0,1],[i,i], s=(2*.2*i)**2)
arrow = mpl.patches.FancyArrowPatch((0,i), (1,i),
arrowstyle='-|>,head_width={},head_length={}'.format(i/5.,.4*i))
ax.add_patch(arrow)
ax.text(1.2,i,"mutation_scale = {}".format(i),
va="center")
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