1

This is goes in the same direction as this question.

I want to point an arrow from one scatter point to another, so that the arrow head lies next to edge of the marker. Like in the following example:

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(posA=(0,0), posB=(1,1), arrowstyle='-|>', mutation_scale=20, shrinkA=7, shrinkB=7)
plt.show()

enter image description here

Here I chose the values of shrinkA and shrinkB manually so that the arrow head is lying very close from the edge of the target scatter point. However, I would have to change those values if I change the size of the markers.

My question is: Knowing the size of the markers (kwarg s in ax.scatter), how can chose shrinkA and shrinkB so that the arrow lies close from the marker's edge?

I know that s is measured in p^2 where p is a typographic point. So that the radius of the marker is sqrt(s / pi). If shrinkA and shrinkB are measured in the same typographic points, we could just do shrinkB=radius where radius is the radius of the marker.

For s==300 this makes sense as the radius is close to 9.8.

rodgdor
  • 2,530
  • 1
  • 19
  • 26

1 Answers1

2

The shrinkA/shrinkB arguments of FancyArrowPatch expect their argument in units of points. Points is also the unit of linewidth or markersize. For a scatter plot, the size argument s is the square of the markersize.

So given the size of the scatter plot, s=size, the shrink is calculated by taking the squareroot and dividing by 2 (because you want to shrink the arrow by the radius, not the diameter).

shrink = math.sqrt(size)/2.

Example:

import matplotlib.pyplot as plt
import matplotlib as mpl
import math

fig, ax = plt.subplots()
size = 1000
radius = math.sqrt(size)/2.
points = ax.scatter([0,1], [0,1], s=size)
arrow = mpl.patches.FancyArrowPatch(posA=(0,0), posB=(1,1), 
                                    arrowstyle='-|>', mutation_scale=20, 
                                    shrinkA=radius, shrinkB=radius)
ax.add_patch(arrow)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712