0

I am trying to center an axis text object by:

  1. Getting the width in coordinates of the text divided by 2.
  2. Subtracting that value from the center (provided) location on the x-axis.
  3. Using the resulting value as the x starting position (with ha='left').

I have seen examples of how to get x-coordinates (bounds) after plotting a string like this:

import matplotlib as plt

f = plt.figure()
r = f.canvas.get_renderer()
t = plt.text(0, 0, 'test')
bb = t.get_window_extent(renderer=r)
width = bb.width

However, I would like to know the width (in axis coordinates) of a string before plotting so that I can anticipate an adjustment to make.

I've tried the following, but it did not return the correct axis coordinates and I think a transformation may need to occur:

t = matplotlib.textpath.TextPath((0,0), 'test', size=9)
bb = t.get_extents()
w = bb.width   #16.826132812499999

Here's a sample to work with (last 3 lines show what I want to do):

import matplotlib.pyplot as plt
import matplotlib
import numpy as np
%matplotlib inline
prf=[60,70,65,83,77,70,71]
figsize=3.5,4
fig, ax = plt.subplots(1, 1, figsize = figsize, dpi=300)
ind=np.arange(len(prf))

p=ax.bar(ind,prf,color=colrs,edgecolor='none')
t = matplotlib.textpath.TextPath((0,0), 'test', size=9)
bb = t.get_extents()
w = bb.width
center=len(ind)/2
xposition=center-w/2
ax.text(xposition,110,'test',size=9)

This question is a follow-up from this post.

I know I can use ha='center', but this is actually for a more complex text (multi-colored), which does not provide that option.

Thanks in advance!

Dance Party2
  • 7,214
  • 17
  • 59
  • 106
  • I think I do not sufficiently understand the problem. Where do you want to position the text? (You say axes coordinates, but 110 is out of the axes,isn't it?) – ImportanceOfBeingErnest Nov 28 '17 at 19:10
  • I just need to know the length of a string, in axis coordinates, if I were to plot it so that I can use it for plotting other text (all without actually plotting anything to get the coordiantes). – Dance Party2 Nov 28 '17 at 19:16
  • Nobody knows the width a text will have up to the point where it is plotted. But that usually is no problem because you can draw it, get the size and remove it again. Still I have the suspicion that "axis coordinates" is not really what you want (or maybe you use it with a different meaning in mind). So better explain *where* you want to position the text. – ImportanceOfBeingErnest Nov 28 '17 at 19:21
  • Assuming the horizontal alignment is left with a given font size and weight, I want to know what to use as the x value in order to do ax.text(x,y,'string',ha='left') such that the string will be centered. – Dance Party2 Nov 28 '17 at 19:24

1 Answers1

2

You can create a text object, obtain its bounding box and then remove the text again. You may transform the bounding box into data coordinates (I assume that you mean data coordinates, not axes coordinates in the question) and use those to create a left aligned text.

import matplotlib.pyplot as plt

ax = plt.gca()
ax.set_xlim(0,900)
#create centered text 
text = ax.text(400,0.5, "string", ha="center", color="blue")
plt.gcf().canvas.draw()
bb = text.get_window_extent()
# remove centered text
text.remove()
del text
# create left aligned text from position of centered text
bb2 = bb.transformed(ax.transData.inverted())
text = ax.text(bb2.x0,0.5, "string", ha="left", color="red")

plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • I think I need axis coordinates because it's for a title. No? I'll see what I can do with this as it is for now. – Dance Party2 Nov 28 '17 at 20:27
  • I really don't know. I asked several times where to position the text. Now I gave an answer with what information I had and that is 110 in the ycoordinate- which does not make sense as axes coordinate - so I chose data coordinates. Feel free to use axes coordinates if you want. – ImportanceOfBeingErnest Nov 28 '17 at 20:33
  • Nevermind, I see what I was doing wrong now. Data coordinates were correct. Thanks! – Dance Party2 Nov 28 '17 at 20:45
  • Note for later: for the x coordinate in the first instance, I used (len(ind)/2)-0.5 instead of 400 (and did not set the ylim values). – Dance Party2 Nov 28 '17 at 21:17