lo tolmencre
lo tolmencre

Reputation: 3934

Add text to inter-axes arrow

Yesterday I asked a question based on a misconception. I now know better what actually I am asking.

I want to draw an arrow between two axeses AND have text next to it like I manually painted in here:

enter image description here

import matplotlib.pyplot as plt
from matplotlib import patches
import numpy as np

fig = plt.figure()

X, Y = np.mgrid[-1:1:.1, -1:1:.1]
Z = X+Y

ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(313)
ax1.contourf(X, Y, Z)
ax2.contourf(X, Y, -Z)

con = patches.ConnectionPatch((0,0),
                              (0,0),
                              coordsA="data",
                              coordsB="data",
                              arrowstyle="<|-",
                              mutation_scale=20,
                              axesA=ax2,
                              axesB=ax1)
ax2.add_artist(con)

fig.show()

Having arrows with text next to them within one axes can be done with ax.annotate(). Drawing arrows between axeses can be done with ConnectionPatch. However, the docs say:

The ConnectionPatch is like an annotation without text. While the annotate function is recommended in most situations, the ConnectionPatch is useful when you want to connect points in different axes.

So, from that it sounds like having both of these (inter-axes arrow and text) is not covered by the API in a user-friendly manner.

Okay... but there must be an at least palatable way of pulling this off, right? The answer to my question from yesterday was based on my misconception. So, I hope there is a better solution based on this my re-framed question.

So, is there a robust way to add text to an inter-axes-arrow (like ConnectionPatch), without fiddling around with coordinates and ax.text or such nonsense?

Upvotes: 5

Views: 1067

Answers (1)

Ulrich Stern
Ulrich Stern

Reputation: 11301

A "coordinate fiddling" solution requires little code and is quite flexible:

import matplotlib.pyplot as plt
from matplotlib import patches
import numpy as np

fig = plt.figure()

X, Y = np.mgrid[-1:1:.1, -1:1:.1]
Z = X+Y

ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(313)
ax1.contourf(X, Y, Z)
ax2.contourf(X, Y, -Z)

xy1, xy2 = (0,0), (0,0)
con = patches.ConnectionPatch(xy2,
                              xy1,
                              coordsA="data",
                              coordsB="data",
                              arrowstyle="<|-",
                              mutation_scale=20,
                              axesA=ax2,
                              axesB=ax1)
ax2.add_artist(con)

# calculate center of inter-axes arrow in figure pixels
xy = np.mean([ax1.transData.transform(xy1), ax2.transData.transform(xy2)],
  axis=0)
plt.annotate(" arrow label", xy, xycoords='figure pixels', va='center')

plt.show()

Here the result:labeled arrow

Upvotes: 3

Related Questions