Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper Mutational scale value in matplotlib

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.

enter image description here

However, when I use:

arrow = mpl.patches.FancyArrowPatch((0,0), (1,1), arrowstyle='-|>', mutational_aspect=20)

I get the proper arrow. enter image description here

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?

like image 270
rodgdor Avatar asked Nov 18 '25 16:11

rodgdor


1 Answers

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()

enter image description here

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()
like image 188
ImportanceOfBeingErnest Avatar answered Nov 21 '25 06:11

ImportanceOfBeingErnest