2
2
unicode_literals )
3
3
4
4
import six
5
+ import warnings
5
6
6
7
import numpy as np
8
+ from numpy .testing import assert_almost_equal
9
+ from nose .tools import eq_
10
+
11
+ from matplotlib .transforms import Bbox
7
12
import matplotlib
8
- from matplotlib .testing .decorators import image_comparison , knownfailureif , cleanup
9
13
import matplotlib .pyplot as plt
10
- import warnings
11
- from nose .tools import with_setup
14
+ from matplotlib .testing .decorators import image_comparison , cleanup
15
+ from matplotlib .figure import Figure
16
+ from matplotlib .text import Annotation , Text
17
+ from matplotlib .backends .backend_agg import RendererAgg
12
18
13
19
14
20
@image_comparison (baseline_images = ['font_styles' ])
@@ -22,79 +28,98 @@ def find_matplotlib_font(**kw):
22
28
return FontProperties (fname = path )
23
29
24
30
from matplotlib .font_manager import FontProperties , findfont
25
- warnings .filterwarnings ('ignore' , ('findfont: Font family \[u?\' Foo\' \] ' +
26
- 'not found. Falling back to .' ),
27
- UserWarning ,
28
- module = 'matplotlib.font_manager' )
29
- fig = plt .figure ()
31
+ warnings .filterwarnings (
32
+ 'ignore' ,
33
+ ('findfont: Font family \[u?\' Foo\' \] not found. Falling back to .' ),
34
+ UserWarning ,
35
+ module = 'matplotlib.font_manager' )
36
+
37
+ plt .figure ()
30
38
ax = plt .subplot (1 , 1 , 1 )
31
39
32
- normalFont = find_matplotlib_font (family = "sans-serif" ,
33
- style = "normal" ,
34
- variant = "normal" ,
35
- size = 14 ,
36
- )
37
- ax .annotate ("Normal Font" , (0.1 , 0.1 ), xycoords = 'axes fraction' ,
38
- fontproperties = normalFont )
39
-
40
- boldFont = find_matplotlib_font (family = "Foo" ,
41
- style = "normal" ,
42
- variant = "normal" ,
43
- weight = "bold" ,
44
- stretch = 500 ,
45
- size = 14 ,
46
- )
47
- ax .annotate ("Bold Font" , (0.1 , 0.2 ), xycoords = 'axes fraction' ,
48
- fontproperties = boldFont )
49
-
50
- boldItemFont = find_matplotlib_font (family = "sans serif" ,
51
- style = "italic" ,
52
- variant = "normal" ,
53
- weight = 750 ,
54
- stretch = 500 ,
55
- size = 14 ,
56
- )
57
- ax .annotate ("Bold Italic Font" , (0.1 , 0.3 ), xycoords = 'axes fraction' ,
58
- fontproperties = boldItemFont )
59
-
60
- lightFont = find_matplotlib_font (family = "sans-serif" ,
61
- style = "normal" ,
62
- variant = "normal" ,
63
- weight = 200 ,
64
- stretch = 500 ,
65
- size = 14 ,
66
- )
67
- ax .annotate ("Light Font" , (0.1 , 0.4 ), xycoords = 'axes fraction' ,
68
- fontproperties = lightFont )
69
-
70
- condensedFont = find_matplotlib_font (family = "sans-serif" ,
71
- style = "normal" ,
72
- variant = "normal" ,
73
- weight = 500 ,
74
- stretch = 100 ,
75
- size = 14 ,
76
- )
77
- ax .annotate ("Condensed Font" , (0.1 , 0.5 ), xycoords = 'axes fraction' ,
78
- fontproperties = condensedFont )
40
+ normalFont = find_matplotlib_font (
41
+ family = "sans-serif" ,
42
+ style = "normal" ,
43
+ variant = "normal" ,
44
+ size = 14 )
45
+ ax .annotate (
46
+ "Normal Font" ,
47
+ (0.1 , 0.1 ),
48
+ xycoords = 'axes fraction' ,
49
+ fontproperties = normalFont )
50
+
51
+ boldFont = find_matplotlib_font (
52
+ family = "Foo" ,
53
+ style = "normal" ,
54
+ variant = "normal" ,
55
+ weight = "bold" ,
56
+ stretch = 500 ,
57
+ size = 14 )
58
+ ax .annotate (
59
+ "Bold Font" ,
60
+ (0.1 , 0.2 ),
61
+ xycoords = 'axes fraction' ,
62
+ fontproperties = boldFont )
63
+
64
+ boldItemFont = find_matplotlib_font (
65
+ family = "sans serif" ,
66
+ style = "italic" ,
67
+ variant = "normal" ,
68
+ weight = 750 ,
69
+ stretch = 500 ,
70
+ size = 14 )
71
+ ax .annotate (
72
+ "Bold Italic Font" ,
73
+ (0.1 , 0.3 ),
74
+ xycoords = 'axes fraction' ,
75
+ fontproperties = boldItemFont )
76
+
77
+ lightFont = find_matplotlib_font (
78
+ family = "sans-serif" ,
79
+ style = "normal" ,
80
+ variant = "normal" ,
81
+ weight = 200 ,
82
+ stretch = 500 ,
83
+ size = 14 )
84
+ ax .annotate (
85
+ "Light Font" ,
86
+ (0.1 , 0.4 ),
87
+ xycoords = 'axes fraction' ,
88
+ fontproperties = lightFont )
89
+
90
+ condensedFont = find_matplotlib_font (
91
+ family = "sans-serif" ,
92
+ style = "normal" ,
93
+ variant = "normal" ,
94
+ weight = 500 ,
95
+ stretch = 100 ,
96
+ size = 14 )
97
+ ax .annotate (
98
+ "Condensed Font" ,
99
+ (0.1 , 0.5 ),
100
+ xycoords = 'axes fraction' ,
101
+ fontproperties = condensedFont )
79
102
80
103
ax .set_xticks ([])
81
104
ax .set_yticks ([])
82
105
83
106
84
107
@image_comparison (baseline_images = ['multiline' ])
85
108
def test_multiline ():
86
- fig = plt .figure ()
109
+ plt .figure ()
87
110
ax = plt .subplot (1 , 1 , 1 )
88
111
ax .set_title ("multiline\n text alignment" )
89
112
90
- plt .text (0.2 , 0.5 , "TpTpTp \n $M$ \n TpTpTp" , size = 20 ,
91
- ha = "center" , va = "top" )
113
+ plt .text (
114
+ 0.2 , 0.5 , "TpTpTp \n $M$ \n TpTpTp" , size = 20 , ha = "center" , va = "top" )
92
115
93
- plt .text (0.5 , 0.5 , "TpTpTp\n $M^{M^{M^{M}}}$\n TpTpTp" , size = 20 ,
94
- ha = "center" , va = "top" )
116
+ plt .text (
117
+ 0.5 , 0.5 , "TpTpTp\n $M^{M^{M^{M}}}$\n TpTpTp" , size = 20 ,
118
+ ha = "center" , va = "top" )
95
119
96
- plt .text (0.8 , 0.5 , "TpTpTp\n $M_{q_{q_{q}}}$\n TpTpTp" , size = 20 ,
97
- ha = "center" , va = "top" )
120
+ plt .text (
121
+ 0.8 , 0.5 , "TpTpTp\n $M_{q_{q_{q}}}$\n TpTpTp" , size = 20 ,
122
+ ha = "center" , va = "top" )
98
123
99
124
plt .xlim (0 , 1 )
100
125
plt .ylim (0 , 0.8 )
@@ -135,15 +160,15 @@ def test_contains():
135
160
fig = plt .figure ()
136
161
ax = plt .axes ()
137
162
138
- mevent = mbackend .MouseEvent ('button_press_event' , fig . canvas , 0.5 ,
139
- 0.5 , 1 , None )
163
+ mevent = mbackend .MouseEvent (
164
+ 'button_press_event' , fig . canvas , 0.5 , 0.5 , 1 , None )
140
165
141
166
xs = np .linspace (0.25 , 0.75 , 30 )
142
167
ys = np .linspace (0.25 , 0.75 , 30 )
143
168
xs , ys = np .meshgrid (xs , ys )
144
169
145
- txt = plt .text (0.48 , 0.52 , 'hello world' , ha = 'center' , fontsize = 30 ,
146
- rotation = 30 )
170
+ txt = plt .text (
171
+ 0.48 , 0.52 , 'hello world' , ha = 'center' , fontsize = 30 , rotation = 30 )
147
172
# uncomment to draw the text's bounding box
148
173
# txt.set_bbox(dict(edgecolor='black', facecolor='none'))
149
174
@@ -153,9 +178,7 @@ def test_contains():
153
178
154
179
for x , y in zip (xs .flat , ys .flat ):
155
180
mevent .x , mevent .y = plt .gca ().transAxes .transform_point ([x , y ])
156
-
157
181
contains , _ = txt .contains (mevent )
158
-
159
182
color = 'yellow' if contains else 'red'
160
183
161
184
# capture the viewLim, plot a point, and reset the viewLim
@@ -167,7 +190,7 @@ def test_contains():
167
190
@image_comparison (baseline_images = ['titles' ])
168
191
def test_titles ():
169
192
# left and right side titles
170
- fig = plt .figure ()
193
+ plt .figure ()
171
194
ax = plt .subplot (1 , 1 , 1 )
172
195
ax .set_title ("left title" , loc = "left" )
173
196
ax .set_title ("right title" , loc = "right" )
@@ -177,15 +200,17 @@ def test_titles():
177
200
178
201
@image_comparison (baseline_images = ['text_alignment' ])
179
202
def test_alignment ():
180
- fig = plt .figure ()
203
+ plt .figure ()
181
204
ax = plt .subplot (1 , 1 , 1 )
182
205
183
206
x = 0.1
184
207
for rotation in (0 , 30 ):
185
208
for alignment in ('top' , 'bottom' , 'baseline' , 'center' ):
186
- ax .text (x , 0.5 , alignment + " Tj" , va = alignment , rotation = rotation ,
187
- bbox = dict (boxstyle = 'round' , facecolor = 'wheat' , alpha = 0.5 ))
188
- ax .text (x , 1.0 , r'$\sum_{i=0}^{j}$' , va = alignment , rotation = rotation )
209
+ ax .text (
210
+ x , 0.5 , alignment + " Tj" , va = alignment , rotation = rotation ,
211
+ bbox = dict (boxstyle = 'round' , facecolor = 'wheat' , alpha = 0.5 ))
212
+ ax .text (
213
+ x , 1.0 , r'$\sum_{i=0}^{j}$' , va = alignment , rotation = rotation )
189
214
x += 0.1
190
215
191
216
ax .plot ([0 , 1 ], [0.5 , 0.5 ])
@@ -200,8 +225,8 @@ def test_alignment():
200
225
@image_comparison (baseline_images = ['axes_titles' ], extensions = ['png' ])
201
226
def test_axes_titles ():
202
227
# Related to issue #3327
203
- fig = plt .figure ()
204
- ax = plt .subplot (1 ,1 , 1 )
228
+ plt .figure ()
229
+ ax = plt .subplot (1 , 1 , 1 )
205
230
ax .set_title ('center' , loc = 'center' , fontsize = 20 , fontweight = 700 )
206
231
ax .set_title ('left' , loc = 'left' , fontsize = 12 , fontweight = 400 )
207
232
ax .set_title ('right' , loc = 'right' , fontsize = 12 , fontweight = 400 )
@@ -212,7 +237,8 @@ def test_set_position():
212
237
fig , ax = plt .subplots ()
213
238
214
239
# test set_position
215
- ann = ax .annotate ('test' , (0 , 0 ), xytext = (0 , 0 ), textcoords = 'figure pixels' )
240
+ ann = ax .annotate (
241
+ 'test' , (0 , 0 ), xytext = (0 , 0 ), textcoords = 'figure pixels' )
216
242
plt .draw ()
217
243
218
244
init_pos = ann .get_window_extent (fig .canvas .renderer )
@@ -225,7 +251,8 @@ def test_set_position():
225
251
assert a + shift_val == b
226
252
227
253
# test xyann
228
- ann = ax .annotate ('test' , (0 , 0 ), xytext = (0 , 0 ), textcoords = 'figure pixels' )
254
+ ann = ax .annotate (
255
+ 'test' , (0 , 0 ), xytext = (0 , 0 ), textcoords = 'figure pixels' )
229
256
plt .draw ()
230
257
231
258
init_pos = ann .get_window_extent (fig .canvas .renderer )
@@ -260,3 +287,116 @@ def test_annotation_negative_coords():
260
287
ax .annotate ("-fpx" , (- 45 , - 30 ), xycoords = "figure pixels" )
261
288
ax .annotate ("-apt" , (- 35 , - 20 ), xycoords = "axes points" )
262
289
ax .annotate ("-apx" , (- 25 , - 10 ), xycoords = "axes pixels" )
290
+
291
+
292
+ @cleanup
293
+ def test_text_annotation_get_window_extent ():
294
+ figure = Figure (dpi = 100 )
295
+ renderer = RendererAgg (200 , 200 , 100 )
296
+
297
+ # Only text annotation
298
+ annotation = Annotation ('test' , xy = (0 , 0 ))
299
+ annotation .set_figure (figure )
300
+
301
+ text = Text (text = 'test' , x = 0 , y = 0 )
302
+ text .set_figure (figure )
303
+
304
+ bbox = annotation .get_window_extent (renderer = renderer )
305
+
306
+ text_bbox = text .get_window_extent (renderer = renderer )
307
+ eq_ (bbox .width , text_bbox .width )
308
+ eq_ (bbox .height , text_bbox .height )
309
+
310
+ _ , _ , d = renderer .get_text_width_height_descent (
311
+ 'text' , annotation ._fontproperties , ismath = False )
312
+ _ , _ , lp_d = renderer .get_text_width_height_descent (
313
+ 'lp' , annotation ._fontproperties , ismath = False )
314
+ below_line = max (d , lp_d )
315
+
316
+ # These numbers are specific to the current implementation of Text
317
+ points = bbox .get_points ()
318
+ eq_ (points [0 , 0 ], 0.0 )
319
+ eq_ (points [1 , 0 ], text_bbox .width )
320
+ eq_ (points [0 , 1 ], - below_line )
321
+ eq_ (points [1 , 1 ], text_bbox .height - below_line )
322
+
323
+
324
+ @cleanup
325
+ def test_text_with_arrow_annotation_get_window_extent ():
326
+ headwidth = 21
327
+ fig , ax = plt .subplots (dpi = 100 )
328
+ txt = ax .text (s = 'test' , x = 0 , y = 0 )
329
+ ann = ax .annotate ('test' ,
330
+ xy = (0.0 , 50.0 ),
331
+ xytext = (50.0 , 50.0 ), xycoords = 'figure pixels' ,
332
+ arrowprops = {
333
+ 'facecolor' : 'black' , 'width' : 2 ,
334
+ 'headwidth' : headwidth , 'shrink' : 0.0 })
335
+
336
+ plt .draw ()
337
+ renderer = fig .canvas .renderer
338
+ # bounding box of text
339
+ text_bbox = txt .get_window_extent (renderer = renderer )
340
+ # bounding box of annotation (text + arrow)
341
+ bbox = ann .get_window_extent (renderer = renderer )
342
+ # bounding box of arrow
343
+ arrow_bbox = ann .arrow .get_window_extent (renderer )
344
+ # bounding box of annotation text
345
+ ann_txt_bbox = Text .get_window_extent (ann )
346
+
347
+ # make sure annotation with in 50 px wider than
348
+ # just the text
349
+ eq_ (bbox .width , text_bbox .width + 50.0 )
350
+ # make sure the annotation text bounding box is same size
351
+ # as the bounding box of the same string as a Text object
352
+ eq_ (ann_txt_bbox .height , text_bbox .height )
353
+ eq_ (ann_txt_bbox .width , text_bbox .width )
354
+ # compute the expected bounding box of arrow + text
355
+ expected_bbox = Bbox .union ([ann_txt_bbox , arrow_bbox ])
356
+ assert_almost_equal (bbox .height , expected_bbox .height )
357
+
358
+
359
+ @cleanup
360
+ def test_arrow_annotation_get_window_extent ():
361
+ figure = Figure (dpi = 100 )
362
+ figure .set_figwidth (2.0 )
363
+ figure .set_figheight (2.0 )
364
+ renderer = RendererAgg (200 , 200 , 100 )
365
+
366
+ # Text annotation with arrow
367
+ annotation = Annotation (
368
+ '' , xy = (0.0 , 50.0 ), xytext = (50.0 , 50.0 ), xycoords = 'figure pixels' ,
369
+ arrowprops = {
370
+ 'facecolor' : 'black' , 'width' : 8 , 'headwidth' : 10 , 'shrink' : 0.0 })
371
+ annotation .set_figure (figure )
372
+ annotation .draw (renderer )
373
+
374
+ bbox = annotation .get_window_extent ()
375
+ points = bbox .get_points ()
376
+
377
+ eq_ (bbox .width , 50.0 )
378
+ assert_almost_equal (bbox .height , 10.0 / 0.72 )
379
+ eq_ (points [0 , 0 ], 0.0 )
380
+ eq_ (points [0 , 1 ], 50.0 - 5 / 0.72 )
381
+
382
+
383
+ @cleanup
384
+ def test_empty_annotation_get_window_extent ():
385
+ figure = Figure (dpi = 100 )
386
+ figure .set_figwidth (2.0 )
387
+ figure .set_figheight (2.0 )
388
+ renderer = RendererAgg (200 , 200 , 100 )
389
+
390
+ # Text annotation with arrow
391
+ annotation = Annotation (
392
+ '' , xy = (0.0 , 50.0 ), xytext = (0.0 , 50.0 ), xycoords = 'figure pixels' )
393
+ annotation .set_figure (figure )
394
+ annotation .draw (renderer )
395
+
396
+ bbox = annotation .get_window_extent ()
397
+ points = bbox .get_points ()
398
+
399
+ eq_ (points [0 , 0 ], 0.0 )
400
+ eq_ (points [1 , 0 ], 0.0 )
401
+ eq_ (points [1 , 1 ], 50.0 )
402
+ eq_ (points [0 , 1 ], 50.0 )
0 commit comments