Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotation refactor #2351

Merged
merged 4 commits into from Sep 10, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/api/api_changes.rst
Expand Up @@ -59,9 +59,24 @@ original location:
thus `colorbar.ColorbarBase.outline` is now a
`matplotlib.patches.Polygon` object.


* The rcParams `savefig.transparent` has been added to control
default transparency when saving figures.

* Slightly refactored the `Annotation` family. The text location in
`Annotation` is now handled entirely handled by the underlying `Text`
object so `set_position` works as expected. The attributes `xytext` and
`textcoords` have been deprecated in favor of `xyann` and `anncoords` so
that `Annotation` and `AnnotaionBbox` can share a common sensibly named
api for getting/setting the location of the text or box.

- `xyann` -> set the location of the annotation
- `xy` -> set where the arrow points to
- `anncoords` -> set the units of the annotation location
- `xycoords` -> set the units of the point location
- `set_position()` -> `Annotation` only set location of annotation


.. _changes_in_1_3:


Expand Down
54 changes: 36 additions & 18 deletions lib/matplotlib/offsetbox.py
Expand Up @@ -1265,6 +1265,10 @@ def __init__(self, offsetbox, xy,

self.set_fontsize(fontsize)

self.xybox = xybox

self.boxcoords = boxcoords

if arrowprops is not None:
self._arrow_relpos = self.arrowprops.pop("relpos", (0.5, 0.5))
self.arrow_patch = FancyArrowPatch((0, 0), (1, 1),
Expand All @@ -1274,8 +1278,8 @@ def __init__(self, offsetbox, xy,
self.arrow_patch = None

_AnnotationBase.__init__(self,
xy, xytext=xybox,
xycoords=xycoords, textcoords=boxcoords,
xy,
xycoords=xycoords,
annotation_clip=annotation_clip)

martist.Artist.__init__(self, **kwargs)
Expand All @@ -1295,6 +1299,22 @@ def __init__(self, offsetbox, xy,
self.patch.set(**bboxprops)
self._drawFrame = frameon

@property
def xyann(self):
return self.xybox

@xyann.setter
def xyann(self, xyann):
self.xybox = xyann

@property
def anncoords(self):
return self.boxcoords

@anncoords.setter
def anncoords(self, coords):
self.boxcoords = coords

def contains(self, event):
t, tinfo = self.offsetbox.contains(event)
#if self.arrow_patch is not None:
Expand Down Expand Up @@ -1352,14 +1372,14 @@ def _update_position_xybox(self, renderer, xy_pixel):
patch.
"""

x, y = self.xytext
if isinstance(self.textcoords, tuple):
xcoord, ycoord = self.textcoords
x, y = self.xybox
if isinstance(self.boxcoords, tuple):
xcoord, ycoord = self.boxcoords
x1, y1 = self._get_xy(renderer, x, y, xcoord)
x2, y2 = self._get_xy(renderer, x, y, ycoord)
ox0, oy0 = x1, y2
else:
ox0, oy0 = self._get_xy(renderer, x, y, self.textcoords)
ox0, oy0 = self._get_xy(renderer, x, y, self.boxcoords)

w, h, xd, yd = self.offsetbox.get_extent(renderer)

Expand Down Expand Up @@ -1579,32 +1599,30 @@ def __init__(self, annotation, use_blit=False):

def save_offset(self):
ann = self.annotation
x, y = ann.xytext
if isinstance(ann.textcoords, tuple):
xcoord, ycoord = ann.textcoords
x, y = ann.xyann
if isinstance(ann.anncoords, tuple):
xcoord, ycoord = ann.anncoords
x1, y1 = ann._get_xy(self.canvas.renderer, x, y, xcoord)
x2, y2 = ann._get_xy(self.canvas.renderer, x, y, ycoord)
ox0, oy0 = x1, y2
else:
ox0, oy0 = ann._get_xy(self.canvas.renderer, x, y, ann.textcoords)
ox0, oy0 = ann._get_xy(self.canvas.renderer, x, y, ann.anncoords)

self.ox, self.oy = ox0, oy0
self.annotation.textcoords = "figure pixels"
self.annotation.anncoords = "figure pixels"
self.update_offset(0, 0)

def update_offset(self, dx, dy):
ann = self.annotation
ann.xytext = self.ox + dx, self.oy + dy
x, y = ann.xytext
# xy is never used
xy = ann._get_xy(self.canvas.renderer, x, y, ann.textcoords)
ann.xyann = self.ox + dx, self.oy + dy
x, y = ann.xyann

def finalize_offset(self):
loc_in_canvas = self.annotation.xytext
self.annotation.textcoords = "axes fraction"
loc_in_canvas = self.annotation.xyann
self.annotation.anncoords = "axes fraction"
pos_axes_fraction = self.annotation.axes.transAxes.inverted()
pos_axes_fraction = pos_axes_fraction.transform_point(loc_in_canvas)
self.annotation.xytext = tuple(pos_axes_fraction)
self.annotation.xyann = tuple(pos_axes_fraction)


if __name__ == "__main__":
Expand Down
124 changes: 78 additions & 46 deletions lib/matplotlib/tests/test_text.py
Expand Up @@ -21,60 +21,60 @@ def find_matplotlib_font(**kw):
return FontProperties(fname=path)

from matplotlib.font_manager import FontProperties, findfont
warnings.filterwarnings('ignore','findfont: Font family \[\'Foo\'\] '+ \
warnings.filterwarnings('ignore', 'findfont: Font family \[\'Foo\'\] '+ \
'not found. Falling back to .',
UserWarning,
module='matplotlib.font_manager')
fig = plt.figure()
ax = plt.subplot( 1, 1, 1 )

normalFont = find_matplotlib_font( family = "sans-serif",
style = "normal",
variant = "normal",
size = 14,
)
ax.annotate( "Normal Font", (0.1, 0.1), xycoords='axes fraction',
fontproperties = normalFont )

boldFont = find_matplotlib_font( family = "Foo",
style = "normal",
variant = "normal",
weight = "bold",
stretch = 500,
size = 14,
ax = plt.subplot(1, 1, 1)

normalFont = find_matplotlib_font(family="sans-serif",
style="normal",
variant="normal",
size=14,
)
ax.annotate("Normal Font", (0.1, 0.1), xycoords='axes fraction',
fontproperties=normalFont)

boldFont = find_matplotlib_font(family="Foo",
style="normal",
variant="normal",
weight="bold",
stretch=500,
size=14,
)
ax.annotate( "Bold Font", (0.1, 0.2), xycoords='axes fraction',
fontproperties = boldFont )

boldItemFont = find_matplotlib_font( family = "sans serif",
style = "italic",
variant = "normal",
weight = 750,
stretch = 500,
size = 14,
ax.annotate("Bold Font", (0.1, 0.2), xycoords='axes fraction',
fontproperties=boldFont)

boldItemFont = find_matplotlib_font(family="sans serif",
style="italic",
variant="normal",
weight=750,
stretch=500,
size=14,
)
ax.annotate( "Bold Italic Font", (0.1, 0.3), xycoords='axes fraction',
fontproperties = boldItemFont )

lightFont = find_matplotlib_font( family = "sans-serif",
style = "normal",
variant = "normal",
weight = 200,
stretch = 500,
size = 14,
ax.annotate("Bold Italic Font", (0.1, 0.3), xycoords='axes fraction',
fontproperties=boldItemFont)

lightFont = find_matplotlib_font(family="sans-serif",
style="normal",
variant="normal",
weight=200,
stretch=500,
size=14,
)
ax.annotate( "Light Font", (0.1, 0.4), xycoords='axes fraction',
fontproperties = lightFont )

condensedFont = find_matplotlib_font( family = "sans-serif",
style = "normal",
variant = "normal",
weight = 500,
stretch = 100,
size = 14,
ax.annotate("Light Font", (0.1, 0.4), xycoords='axes fraction',
fontproperties=lightFont)

condensedFont = find_matplotlib_font(family="sans-serif",
style="normal",
variant="normal",
weight=500,
stretch=100,
size=14,
)
ax.annotate( "Condensed Font", (0.1, 0.5), xycoords='axes fraction',
fontproperties = condensedFont )
ax.annotate("Condensed Font", (0.1, 0.5), xycoords='axes fraction',
fontproperties=condensedFont)

ax.set_xticks([])
ax.set_yticks([])
Expand All @@ -101,6 +101,7 @@ def test_multiline():
ax.set_xticks([])
ax.set_yticks([])


@image_comparison(baseline_images=['antialiased'], extensions=['png'])
def test_antialiasing():
matplotlib.rcParams['text.antialiased'] = True
Expand Down Expand Up @@ -193,3 +194,34 @@ def test_alignment():
ax.set_ylim([0, 1.5])
ax.set_xticks([])
ax.set_yticks([])


@cleanup
def test_set_position():
fig, ax = plt.subplots()

# test set_position
ann = ax.annotate('test', (0, 0), xytext=(0, 0), textcoords='figure pixels')
plt.draw()

init_pos = ann.get_window_extent(fig.canvas.renderer)
shift_val = 15
ann.set_position((shift_val, shift_val))
plt.draw()
post_pos = ann.get_window_extent(fig.canvas.renderer)

for a, b in zip(init_pos.min, post_pos.min):
assert a + shift_val == b

# test xyann
ann = ax.annotate('test', (0, 0), xytext=(0, 0), textcoords='figure pixels')
plt.draw()

init_pos = ann.get_window_extent(fig.canvas.renderer)
shift_val = 15
ann.xyann = (shift_val, shift_val)
plt.draw()
post_pos = ann.get_window_extent(fig.canvas.renderer)

for a, b in zip(init_pos.min, post_pos.min):
assert a + shift_val == b