Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text object in matplotlib doesn't respond to zooming properly

. Hello, everyone.

I recently try to add text object in my plot. But when I zoom into the text, the text size remains unchanged. What I want to have is that the text size will increase when I zoom in and will decrease when I zoom out.

import matplotlib as mpl
fig=plt.figure()
ax1=fig.add_subplot(111)
ax1.text('','', '',position=[0.5,0.5], text='Y', fontsize='xx-small' )

Any help is appreciated. Thanks~

Supplement-UTC+8 30/04/2013 9:40 AM

Thanks for the suggestion from tcaswell. TextPath does achieve part of my purposes.

I found there is no documentation about textpath in official matplotlib website, so I view the source code to see what it does. Finally, I achieved a not excellent but satisfactory result as follows.

from matplotlib.textpath import TextPath
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path

fig=plt.figure()
ax1=fig.add_subplot(111)
tp1=TextPath((0.5,0.5), r'How do you turn this on?', size=1)
polygon=tp1.to_polygons()
for a in polygon:
    p1=patches.Polygon(a)
    ax1.add_patch(p1)

The not excellent part of this code is that it doesn't support rotation and export the text as filled polygon. Is there any easy way to rotate the text? Can I export the text as non-filled polygon?

like image 935
Ken T Avatar asked Apr 26 '14 02:04

Ken T


People also ask

How do I add text to a plot in Matplotlib?

Text in Matplotlib Plots ¶ 1 Basic text commands ¶. Add text at an arbitrary location of the Axes. ... 2 Labels for x- and y-axis ¶. Specifying the labels for the x- and y-axis is straightforward, via the set_xlabel and set_ylabel methods. 3 Titles ¶. ... 4 Ticks and ticklabels ¶. ... 5 Legends and Annotations ¶. ...

How to control properties of text and its layout with Matplotlib?

Controlling properties of text and its layout with Matplotlib. matplotlib.text.Text instances have a variety of properties which can be configured via keyword arguments to set_title, set_xlabel , text, etc. string e.g., [ 'Sans' | 'Courier' | 'Helvetica' ...]

Does Matplotlib have a font manager?

Matplotlib includes its own matplotlib.font_manager (thanks to Paul Barrett), which implements a cross platform, W3C compliant font finding algorithm. The user has a great deal of control over text properties (font size, font weight, text location and color, etc.) with sensible defaults set in the rc file .

What can you do with Matplotlib?

And significantly, for those interested in mathematical or scientific figures, Matplotlib implements a large number of TeX math symbols and commands, supporting mathematical expressions anywhere in your figure. The following commands are used to create text in the pyplot interface and the object-oriented API:


2 Answers

When you create a Polygon instance, you can specify many keyword arguments, including setting fill = False (see details here):

from matplotlib.textpath import TextPath
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path

fig=plt.figure()
ax1=fig.add_subplot(111)
ax1.set_ylim(-1 , 3)
ax1.set_xlim(-3, 15)
tp1=TextPath((0.0,0.5), r'How do you turn this on?', size=1)
polygon=tp1.to_polygons()
for a in polygon:
    p1=patches.Polygon(a, fill=False)
    ax1.add_patch(p1)

plt.show()

figure image

like image 60
Alex Ten Avatar answered Oct 12 '22 02:10

Alex Ten


Thanks for the question and the pre-work! My solution is just called by the command:

text_fixed_size(ax=ax, text=f'pos=(4,8), h=1', pos=(4,8), h=1, color=c)

and produces the orange output in the following (solid text and holes, like in 'o', not filled) picture. This solution also works for inverted axes. Height and width can be set independently, if needed.

enter image description here

Code

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

def text_fixed_size(ax, text, pos, w=None, h=None, auto_trans=True, color='k'):

    assert not (w is None and h is None)

    tp = mpl.textpath.TextPath((0.0,0.0), text, size=1)
    x0, y0 = np.amin(np.array(tp.vertices), axis=0)
    x1, y1 = np.amax(np.array(tp.vertices), axis=0)
    hax = -np.subtract(*ax.get_xlim())
    wax = -np.subtract(*ax.get_ylim())

    if w is None:
        w = h / (y1 - y0) * ( x1 - x0)
    if h is None:
        h = w / (x1 - x0) * ( y1 - y0)
    if auto_trans:
        w *= np.sign(hax)
        h *= np.sign(wax)

    verts = []
    for vert in tp.vertices:
        vx = vert[0] * w / (x1 - x0) + pos[0]
        vy = vert[1] * h / (y1 - y0) + pos[1]
        verts += [ [vx, vy] ]
    verts = np.array(verts)

    tp = mpl.path.Path(verts, tp.codes)
    ax.add_patch(mpl.patches.PathPatch(tp, facecolor=color, lw=0))

fig, axs = plt.subplots(2, 2)
axs = np.array(axs).T.flatten()

lims = np.array([[0, 15], [0,10]])
for aa, ax in enumerate(axs):
    d0 = int((-(aa%2)+.5)*2)
    d1 = int((-(aa//2)+.5)*2)
    l = np.array([lims[0, ::d0], lims[1, ::d1]])
    ax.set_xlim(l[0, 0], l[0, 1])
    ax.set_ylim(l[1, 0], l[1, 1])

for aa, ax in enumerate(axs):
    c = 'C0'
    text_fixed_size(ax=ax, text=f'pos=(6,3), w=5, h=1',
                    pos=(6,3), w=5, h=1, color=c)
    c = 'C1'
    text_fixed_size(ax=ax, text=f'pos=(4,8), h=1',
                    pos=(4,8), h=1, color=c)
    c = 'C2'
    text_fixed_size(ax=ax, text=f'pos=(8,1), w=5, auto_trans=False',
                    pos=(3,1), w=10, auto_trans=False, color=c)

plt.show()
like image 41
Markus Dutschke Avatar answered Oct 12 '22 04:10

Markus Dutschke