Fixed shift applied to text coordinates with matplotlib

Question:

I’m writing a function based on matplotlib.pyplot that mimics academic plots, i.e. with arrow axes and labels slightly shifted from each arrow head.

I’ld like to place some text shifted from the arrow heads (e.g. 10 pixels up or right), and that shift to be constant, namely independent from the aspect ratio, subplots_adjust, xlim or even the size of the figure window.

With:

fig=plt.figure()
ax=fig.add_subplot(111)

I’ve tried so far:

  • fig.text: just bad when changing the margins with subplots_adjust
  • ax.text: pretty good, but the shift changes when resizing the window…
  • ax.annotate: no noticeable difference with ax.text

The two last attempts are based on a 10×10 pixel shift computed this way:

ax.transAxes.inverted().transform((10,10)) - ax.transAxes.inverted().transform((0,0))

and clip_on=False (or annotation_clip=False) of course.

I also tried to look at the transform applied to the ticklabels since their shift from the spines behaves the way I’m looking for, but I don’t find the details behind their CompositeGenericTransform.

Any help would be appreciated.

Asked By: OrionW9

||

Answers:

matplotlib.transforms.offset_copy is doing the job.

But since I need this offset to apply on several transforms, I used another solution (though not that different).

Let’s create two translations:

# 0.1in translation along x axis
offsetX=matplotlib.transforms.ScaledTranslation(.1,  0, fig.dpi_scale_trans)
# 0.1in translation along y axis
offsetY=matplotlib.transforms.ScaledTranslation( 0, .1, fig.dpi_scale_trans)

Then, to place some text 0.1in right of the x-axis and above the y-axis:

ax.text( 1, 0, "X-axis", transform=ax.transAxes + offsetX )
ax.text( 0, 1, "Y-axis", transform=ax.transAxes + offsetY )

and some text right and below (x0,y0) in data coordinate:

ax.text( x0, y0, "Some text", ha='left', va='top', transform=ax.transData + offsetX - offsetY)
Answered By: OrionW9
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.