Text box adaptable

Hi everyone, and thanks for the amazing library first of all :slight_smile:

Now a short question, I have some graphs and I would like to add some statistical summary as text on the figure.

I see how I can add text and it’s quite easy, the problem is that the text wants a coordinate to write the graph.

And I can’t really know it before since the size of the network (and the axis) are computed and fixed at run-time.
So I should add enough space for the text and then place it, but how do I know how much space it would take?
Thanks,
Andrea

Automatic layouts are difficult to do in matplotlib. This was a design decision trade-off made early in its development. Instead of having matplotlib determining optimal layouts and such, the developers decided that it would be better to give the programmers full control over all placement, and merely establish good defaults.

Just for completeness, I like this page because it talks about the multiple different ways you can specify coordinates for a text object (and corresponding arrow) for placement:

http://matplotlib.sourceforge.net/users/annotations.html

Knowing ahead of time how much space an annotation will take is very difficult, especially if your text involves any LaTeX symbols. However, it is possible. The Text object has some method calls that can return bounding boxes for the text object after it is made:

http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_bbox_patch
http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_window_extent

I haven’t used these myself, so I don’t know exactly what is the difference between them (I think they are different coordinate systems). Once knowing the size of your text object, you can change the position of the object using its set_position() method. It is tricky, but if positioning and layout is very important to you, it is possible to do.

I hope this helps!

Ben Root

···

On Fri, Feb 18, 2011 at 2:41 AM, andrea crotti <andrea.crotti.0@…287…> wrote:

Hi everyone, and thanks for the amazing library first of all :slight_smile:

Now a short question, I have some graphs and I would like to add some statistical summary as text on the figure.

I see how I can add text and it’s quite easy, the problem is that the text wants a coordinate to write the graph.

And I can’t really know it before since the size of the network (and the axis) are computed and fixed at run-time.
So I should add enough space for the text and then place it, but how do I know how much space it would take?

Thanks,
Andrea

2011/2/18 Benjamin Root <ben.root@...1304...>:

Automatic layouts are difficult to do in matplotlib. This was a design
decision trade-off made early in its development. Instead of having
matplotlib determining optimal layouts and such, the developers decided that
it would be better to give the programmers full control over all placement,
and merely establish good defaults.

Just for completeness, I like this page because it talks about the multiple
different ways you can specify coordinates for a text object (and
corresponding arrow) for placement:

http://matplotlib.sourceforge.net/users/annotations.html

Knowing ahead of time how much space an annotation will take is very
difficult, especially if your text involves any LaTeX symbols. However, it
is possible. The Text object has some method calls that can return bounding
boxes for the text object after it is made:

http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_bbox_patch
http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_window_extent

I haven't used these myself, so I don't know exactly what is the difference
between them (I think they are different coordinate systems). Once knowing
the size of your text object, you can change the position of the object
using its set_position() method. It is tricky, but if positioning and
layout is very important to you, it is possible to do.

I hope this helps!

Ben Root

Thanks for the answer, I tried something out but well it's not so trivial.
And I think it doesn't make much sense to add the text inside the same
plot, so I thought about subplot.

I want a bigger subplot on top and one are splitted in two parts below it.

But if I do
subplot(221)
...
subplot(222)
...
subplot(223)
...
it doesn't like it, and I didn't find any example which has this "more
advanced" subplotting.

Once that works it might be easier to compute the size that I need
since the coordinate for the subplot are always from 0 to 1...

Andrea,

If you would like more advanced control over your subplots, matplotlib v1.0.x has the new gridspec feature:

http://matplotlib.sourceforge.net/users/whats_new.html#sophisticated-subplot-grid-layout

Maybe this can help you?
Ben Root

···

On Sun, Feb 27, 2011 at 6:48 AM, andrea crotti <andrea.crotti.0@…287…> wrote:

2011/2/18 Benjamin Root <ben.root@…1304…>:

Automatic layouts are difficult to do in matplotlib. This was a design

decision trade-off made early in its development. Instead of having

matplotlib determining optimal layouts and such, the developers decided that

it would be better to give the programmers full control over all placement,

and merely establish good defaults.

Just for completeness, I like this page because it talks about the multiple

different ways you can specify coordinates for a text object (and

corresponding arrow) for placement:

http://matplotlib.sourceforge.net/users/annotations.html

Knowing ahead of time how much space an annotation will take is very

difficult, especially if your text involves any LaTeX symbols. However, it

is possible. The Text object has some method calls that can return bounding

boxes for the text object after it is made:

http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_bbox_patch

http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.text.Text.get_window_extent

I haven’t used these myself, so I don’t know exactly what is the difference

between them (I think they are different coordinate systems). Once knowing

the size of your text object, you can change the position of the object

using its set_position() method. It is tricky, but if positioning and

layout is very important to you, it is possible to do.

I hope this helps!

Ben Root

Thanks for the answer, I tried something out but well it’s not so trivial.

And I think it doesn’t make much sense to add the text inside the same

plot, so I thought about subplot.

I want a bigger subplot on top and one are splitted in two parts below it.

But if I do

subplot(221)

subplot(222)

subplot(223)

it doesn’t like it, and I didn’t find any example which has this "more

advanced" subplotting.

Once that works it might be easier to compute the size that I need

since the coordinate for the subplot are always from 0 to 1…

Here I am again with the text boxing and scaling.
I'm having some troubles to understand the whole picture, since it seems
that there are so many actors involved.

So suppose I have some text and I want to see how big it is, I thought
I could

t = matplotlib.text.Text(0, 0, "very long string")
t.get_bbox_patch()

to get the size and then do the rest.

but this still returns None, probably because at this point there's
probably something still missing, right?

And when I get the resulting size, how do I make my axes big enough
anyway?

What's the relation between size and axes for example?

Here I am again with the text boxing and scaling.

I’m having some troubles to understand the whole picture, since it seems

that there are so many actors involved.

So suppose I have some text and I want to see how big it is, I thought

I could

t = matplotlib.text.Text(0, 0, “very long string”)

t.get_bbox_patch()

to get the size and then do the rest.

but this still returns None, probably because at this point there’s

probably something still missing, right?

The thing that is missing is that it hasn’t been drawn yet. This is why matplotlib can not act like LaTeX and figure out optimal layouts for you automatically. The bbox for any text object can not be known until draw time.

And when I get the resulting size, how do I make my axes big enough

anyway?

You can use subplots_adjust() to change the spacing between subplots. There should also be a way to change the figure size as well through the figure object.

What’s the relation between size and axes for example?

I am not sure I understand your question.

Ben Root

···

On Mon, Mar 7, 2011 at 5:05 AM, Andrea Crotti <andrea.crotti.0@…287…> wrote:

2011/3/7 Andrea Crotti <andrea.crotti.0@...287...>:

[...]
t = matplotlib.text.Text(0, 0, "very long string")
t.get_bbox_patch()

to get the size and then do the rest.

but this still returns None, probably because at this point there's
probably something still missing, right?

And when I get the resulting size, how do I make my axes big enough
anyway?

As Ben explained you need to draw first. So the usual path is:
1. Draw
2. Figure out the size of potentially problematic things (labels,
titles...) and the space you need.
3. Adjust subplots or whatever needs adjustment to fit.
4. Draw again.

Sort of weird but it works and I think it's widely used.

Goyo

Goyo <goyodiaz@...287...> writes:

As Ben explained you need to draw first. So the usual path is:
1. Draw
2. Figure out the size of potentially problematic things (labels,
titles...) and the space you need.
3. Adjust subplots or whatever needs adjustment to fit.
4. Draw again.

Sort of weird but it works and I think it's widely used.

Goyo

Sorry if I'm annoying, but is there any example about that?
For the text I didn't find anything using bbox_patch to compute the size
and then adapt the size of it, unless I'm blind maybe it would be nice
to add in the website for the future...

And also if I create an object of type matplotlib.Text.text how do I
actually attach it to my current figure?

Thanks,
Andrea

Is there an easy way to draw a piece of text (or whatever) to an off-screen or off-canvas buffer, figure out the size from that, and then use that to draw to the plot?

M

···

On 3/8/11 5:51 AM, Andrea Crotti wrote:

Goyo<goyodiaz@...287...> writes:

As Ben explained you need to draw first. So the usual path is:
1. Draw
2. Figure out the size of potentially problematic things (labels,
titles...) and the space you need.
3. Adjust subplots or whatever needs adjustment to fit.
4. Draw again.

Sort of weird but it works and I think it's widely used.

Goyo

Sorry if I'm annoying, but is there any example about that?
For the text I didn't find anything using bbox_patch to compute the size
and then adapt the size of it, unless I'm blind maybe it would be nice
to add in the website for the future...

And also if I create an object of type matplotlib.Text.text how do I
actually attach it to my current figure?

Thanks,
Andrea

------------------------------------------------------------------------------
What You Don't Know About Data Connectivity CAN Hurt You
This paper provides an overview of data connectivity, details
its effect on application quality, and explores various alternative
solutions. http://p.sf.net/sfu/progress-d2d
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Goyo <goyodiaz@…120…287…> writes:

As Ben explained you need to draw first. So the usual path is:

  1. Draw
  1. Figure out the size of potentially problematic things (labels,

titles…) and the space you need.

  1. Adjust subplots or whatever needs adjustment to fit.
  1. Draw again.

Sort of weird but it works and I think it’s widely used.

Goyo

Sorry if I’m annoying, but is there any example about that?

For the text I didn’t find anything using bbox_patch to compute the size

and then adapt the size of it, unless I’m blind maybe it would be nice

to add in the website for the future…

There is an example for doing something similar, but for tick labels. Hopefully this might be a good demonstration of the concept:

http://matplotlib.sourceforge.net/faq/howto_faq.html#automatically-make-room-for-tick-labels

Seeing this code just reminds me just how messy it is to deal with auto-layouts…

And also if I create an object of type matplotlib.Text.text how do I

actually attach it to my current figure?

Because a Text object is derived from Artist, I believe you can use add_artist() to attach your Text object to an axes object (I haven’t tried this personally).

Ben Root

···

On Tue, Mar 8, 2011 at 4:51 AM, Andrea Crotti <andrea.crotti.0@…287…> wrote: