0
votes

I want to write text on a plot, but I noticed that when I move the horizontal position using matplotlib's panning (P key + mouse dragging) and the text is out of the plot area, it still appears. I would like it to disappear once its position exceeds the limits of the x-axis.

Here is a picture to make myself clearer:

enter image description here

The annotation on the right shouldn't be there. It should be present only if the position of the annotation is inside the x-axis.

Here's my code:

from matplotlib.pyplot import figure, show
import numpy as np

fig = figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
x,y = np.random.rand(2,200)
ax.scatter(x,y)
ax.text(np.mean(x), np.max(y), 'A',
        rotation = 0,
        ha = 'center',
        fontsize = 15,
        bbox=dict(facecolor='yellow',edgecolor='black', boxstyle='round'))
show()

EDIT: Setting clip_on=True makes the annotation disappear, as it should be above the vertical axis maximum. On the following picture, the left shows what happens when that argument is set to True; on the right, the desired image.

enter image description here

1
Note that matplotlib has panning built in. Press the p key and drag the mouse around. text, like other artists, should have a clip_on argument, which, if set to True, would make the artist being clipped by the axes. - ImportanceOfBeingErnest
@ImportanceOfBeingErnest The clip_on argument clips the artist by both axes. Is it possible to do it just for the horizontal one? See updated post to see what I mean. - Tendero
The default clip path is the extent of the axes. But it should be possible to set a different clip path, which is the axes extent in horizontal and the figure extent in vertical direction. Alternatively one can register a callback which sets the visibility of the text, depending on its coordinates. - ImportanceOfBeingErnest
@ImportanceOfBeingErnest I don't really know what you mean by 'path'. I'm kind of a newbie with matplotlib. Is there any place where I could read about this specific topic (clipping, apparently)? - Tendero
It's admidedly not straight forward. Artists can have a clip path set via .set_clip_path. Here would be an example. One would need to use a blended transform for the path though. I will not be able to give a complete answer today, but if you haven't found a solution and no-one else did provide an answer until then feel free to remind me tomorrow. - ImportanceOfBeingErnest

1 Answers

2
votes

When using clip_on=True the default clip path (i.e. the area which clips the artist) is the axes. Here, you want to clip by the axes extent only in x direction. In y direction you would want to clip by the figure extent. This is possible by using a custom clip path.

Such clip path can be a matplotlib patch, e.g. a Rectangle. Then, the rectangle may be defined in a blended coordinate system, such that it extends from 0 to 1 along the x direction in axes coordinates, and from 0 to 1 along the y direction in figure coordinates. Setting the clip path of the text to the hence defined rectangle allows the text to be clipped by the axes in x- and by the figure in y-direction.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans


fig = plt.figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
x,y = np.random.rand(2,200)
ax.scatter(x,y)

trans = mtrans.blended_transform_factory(ax.transAxes, fig.transFigure)
clippath = plt.Rectangle((0,0), 1, 1, transform=trans, clip_on=False)

txt = ax.text(np.mean(x), np.max(y), 'A',
        rotation = 0,
        ha = 'center',
        fontsize = 15,
        bbox=dict(facecolor='yellow',edgecolor='black', boxstyle='round'),
        clip_on=True)
txt.set_clip_path(clippath)

plt.show()

enter image description here