Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 723d015

Browse filesBrowse files
committed
Merge branch 'v2.x'
2 parents e7c51dc + e462aa6 commit 723d015
Copy full SHA for 723d015

File tree

Expand file treeCollapse file tree

9 files changed

+249
-113
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+249
-113
lines changed

‎examples/pylab_examples/barchart_demo2.py

Copy file name to clipboardExpand all lines: examples/pylab_examples/barchart_demo2.py
+140-91Lines changed: 140 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -11,103 +11,152 @@
1111
import numpy as np
1212
import matplotlib.pyplot as plt
1313
from matplotlib.ticker import MaxNLocator
14+
from collections import namedtuple
1415

15-
student = 'Johnny Doe'
16-
grade = 2
17-
gender = 'boy'
18-
cohortSize = 62 # The number of other 2nd grade boys
16+
Student = namedtuple('Student', ['name', 'grade', 'gender'])
17+
Score = namedtuple('Score', ['score', 'percentile'])
1918

20-
numTests = 5
19+
# GLOBAL CONSTANTS
2120
testNames = ['Pacer Test', 'Flexed Arm\n Hang', 'Mile Run', 'Agility',
2221
'Push Ups']
23-
testMeta = ['laps', 'sec', 'min:sec', 'sec', '']
24-
scores = ['7', '48', '12:52', '17', '14']
25-
rankings = np.round(np.random.uniform(0, 1, numTests)*100, 0)
26-
27-
28-
fig, ax1 = plt.subplots(figsize=(9, 7))
29-
plt.subplots_adjust(left=0.115, right=0.88)
30-
fig.canvas.set_window_title('Eldorado K-8 Fitness Chart')
31-
pos = np.arange(numTests) + 0.5 # Center bars on the Y-axis ticks
32-
rects = ax1.barh(pos, rankings, align='center', height=0.5, color='m')
33-
34-
ax1.axis([0, 100, 0, 5])
35-
plt.yticks(pos, testNames)
36-
ax1.set_title('Johnny Doe')
37-
plt.text(50, -0.5, 'Cohort Size: ' + str(cohortSize),
38-
horizontalalignment='center', size='small')
39-
40-
# Set the right-hand Y-axis ticks and labels and set X-axis tick marks at the
41-
# deciles
42-
ax2 = ax1.twinx()
43-
ax2.plot([100, 100], [0, 5], 'white', alpha=0.1)
44-
ax2.xaxis.set_major_locator(MaxNLocator(11))
45-
xticks = plt.setp(ax2, xticklabels=['0', '10', '20', '30', '40', '50', '60',
46-
'70', '80', '90', '100'])
47-
ax2.xaxis.grid(True, linestyle='--', which='major', color='grey',
48-
alpha=0.25)
49-
# Plot a solid vertical gridline to highlight the median position
50-
plt.plot([50, 50], [0, 5], 'grey', alpha=0.25)
51-
52-
# Build up the score labels for the right Y-axis by first appending a carriage
53-
# return to each string and then tacking on the appropriate meta information
54-
# (i.e., 'laps' vs 'seconds'). We want the labels centered on the ticks, so if
55-
# there is no meta info (like for pushups) then don't add the carriage return to
56-
# the string
57-
58-
59-
def withnew(i, scr):
60-
if testMeta[i] != '':
61-
return '%s\n' % scr
22+
testMeta = dict(zip(testNames, ['laps', 'sec', 'min:sec', 'sec', '']))
23+
24+
25+
def attach_ordinal(num):
26+
"""helper function to add ordinal string to integers
27+
28+
1 -> 1st
29+
56 -> 56th
30+
"""
31+
suffixes = dict((str(i), v) for i, v in
32+
enumerate(['th', 'st', 'nd', 'rd', 'th',
33+
'th', 'th', 'th', 'th', 'th']))
34+
35+
v = str(num)
36+
# special case early teens
37+
if v in {'11', '12', '13'}:
38+
return v + 'th'
39+
return v + suffixes[v[-1]]
40+
41+
42+
def format_score(scr, test):
43+
"""
44+
Build up the score labels for the right Y-axis by first
45+
appending a carriage return to each string and then tacking on
46+
the appropriate meta information (i.e., 'laps' vs 'seconds'). We
47+
want the labels centered on the ticks, so if there is no meta
48+
info (like for pushups) then don't add the carriage return to
49+
the string
50+
"""
51+
md = testMeta[test]
52+
if md:
53+
return '{}\n{}'.format(scr, md)
6254
else:
6355
return scr
6456

65-
scoreLabels = [withnew(i, scr) for i, scr in enumerate(scores)]
66-
scoreLabels = [i + j for i, j in zip(scoreLabels, testMeta)]
67-
# set the tick locations
68-
ax2.set_yticks(pos)
69-
# set the tick labels
70-
ax2.set_yticklabels(scoreLabels)
71-
# make sure that the limits are set equally on both yaxis so the ticks line up
72-
ax2.set_ylim(ax1.get_ylim())
73-
74-
75-
ax2.set_ylabel('Test Scores')
76-
# Make list of numerical suffixes corresponding to position in a list
77-
# 0 1 2 3 4 5 6 7 8 9
78-
suffixes = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']
79-
ax2.set_xlabel('Percentile Ranking Across ' + str(grade) + suffixes[grade]
80-
+ ' Grade ' + gender.title() + 's')
81-
82-
# Lastly, write in the ranking inside each bar to aid in interpretation
83-
for rect in rects:
84-
# Rectangle widths are already integer-valued but are floating
85-
# type, so it helps to remove the trailing decimal point and 0 by
86-
# converting width to int type
87-
width = int(rect.get_width())
88-
89-
# Figure out what the last digit (width modulo 10) so we can add
90-
# the appropriate numerical suffix (e.g., 1st, 2nd, 3rd, etc)
91-
lastDigit = width % 10
92-
# Note that 11, 12, and 13 are special cases
93-
if (width == 11) or (width == 12) or (width == 13):
94-
suffix = 'th'
95-
else:
96-
suffix = suffixes[lastDigit]
9757

98-
rankStr = str(width) + suffix
99-
if (width < 5): # The bars aren't wide enough to print the ranking inside
100-
xloc = width + 1 # Shift the text to the right side of the right edge
101-
clr = 'black' # Black against white background
102-
align = 'left'
58+
def format_ycursor(y):
59+
y = int(y)
60+
if y < 0 or y >= len(testNames):
61+
return ''
10362
else:
104-
xloc = 0.98*width # Shift the text to the left side of the right edge
105-
clr = 'white' # White on magenta
106-
align = 'right'
107-
108-
# Center the text vertically in the bar
109-
yloc = rect.get_y() + rect.get_height()/2.0
110-
ax1.text(xloc, yloc, rankStr, horizontalalignment=align,
111-
verticalalignment='center', color=clr, weight='bold')
112-
113-
plt.show()
63+
return testNames[y]
64+
65+
66+
def plot_student_results(student, scores, cohort_size):
67+
# create the figure
68+
fig, ax1 = plt.subplots(figsize=(9, 7))
69+
fig.subplots_adjust(left=0.115, right=0.88)
70+
fig.canvas.set_window_title('Eldorado K-8 Fitness Chart')
71+
72+
pos = np.arange(len(testNames)) + 0.5 # Center bars on the Y-axis ticks
73+
74+
rects = ax1.barh(pos, [scores[k].percentile for k in testNames],
75+
align='center',
76+
height=0.5, color='m',
77+
tick_label=testNames)
78+
79+
ax1.set_title(student.name)
80+
81+
ax1.set_xlim([0, 100])
82+
ax1.xaxis.set_major_locator(MaxNLocator(11))
83+
ax1.xaxis.grid(True, linestyle='--', which='major',
84+
color='grey', alpha=.25)
85+
86+
# Plot a solid vertical gridline to highlight the median position
87+
ax1.axvline(50, color='grey', alpha=0.25)
88+
# set X-axis tick marks at the deciles
89+
cohort_label = ax1.text(.5, -.07, 'Cohort Size: {}'.format(cohort_size),
90+
horizontalalignment='center', size='small',
91+
transform=ax1.transAxes)
92+
93+
# Set the right-hand Y-axis ticks and labels
94+
ax2 = ax1.twinx()
95+
96+
scoreLabels = [format_score(scores[k].score, k) for k in testNames]
97+
98+
# set the tick locations
99+
ax2.set_yticks(pos)
100+
# make sure that the limits are set equally on both yaxis so the
101+
# ticks line up
102+
ax2.set_ylim(ax1.get_ylim())
103+
104+
# set the tick labels
105+
ax2.set_yticklabels(scoreLabels)
106+
107+
ax2.set_ylabel('Test Scores')
108+
109+
ax2.set_xlabel(('Percentile Ranking Across '
110+
'{grade} Grade {gender}s').format(
111+
grade=attach_ordinal(student.grade),
112+
gender=student.gender.title()))
113+
114+
rect_labels = []
115+
# Lastly, write in the ranking inside each bar to aid in interpretation
116+
for rect in rects:
117+
# Rectangle widths are already integer-valued but are floating
118+
# type, so it helps to remove the trailing decimal point and 0 by
119+
# converting width to int type
120+
width = int(rect.get_width())
121+
122+
rankStr = attach_ordinal(width)
123+
# The bars aren't wide enough to print the ranking inside
124+
if (width < 5):
125+
# Shift the text to the right side of the right edge
126+
xloc = width + 1
127+
# Black against white background
128+
clr = 'black'
129+
align = 'left'
130+
else:
131+
# Shift the text to the left side of the right edge
132+
xloc = 0.98*width
133+
# White on magenta
134+
clr = 'white'
135+
align = 'right'
136+
137+
# Center the text vertically in the bar
138+
yloc = rect.get_y() + rect.get_height()/2.0
139+
label = ax1.text(xloc, yloc, rankStr, horizontalalignment=align,
140+
verticalalignment='center', color=clr, weight='bold',
141+
clip_on=True)
142+
rect_labels.append(label)
143+
144+
# make the interactive mouse over give the bar title
145+
ax2.fmt_ydata = format_ycursor
146+
# return all of the artists created
147+
return {'fig': fig,
148+
'ax': ax1,
149+
'ax_right': ax2,
150+
'bars': rects,
151+
'perc_labels': rect_labels,
152+
'cohort_label': cohort_label}
153+
154+
student = Student('Johnny Doe', 2, 'boy')
155+
scores = dict(zip(testNames,
156+
(Score(v, p) for v, p in
157+
zip(['7', '48', '12:52', '17', '14'],
158+
np.round(np.random.uniform(0, 1,
159+
len(testNames))*100, 0)))))
160+
cohort_size = 62 # The number of other 2nd grade boys
161+
162+
arts = plot_student_results(student, scores, cohort_size)

‎lib/matplotlib/animation.py

Copy file name to clipboardExpand all lines: lib/matplotlib/animation.py
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,8 +802,7 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
802802
with writer.saving(self._fig, filename, dpi):
803803
for anim in all_anim:
804804
# Clear the initial frame
805-
if anim._init_func:
806-
anim._init_draw()
805+
anim._init_draw()
807806
for data in zip(*[a.new_saved_frame_seq()
808807
for a in all_anim]):
809808
for anim, d in zip(all_anim, data):
@@ -1022,6 +1021,7 @@ def _step(self, *args):
10221021
# back.
10231022
still_going = Animation._step(self, *args)
10241023
if not still_going and self.repeat:
1024+
self._init_draw()
10251025
self.frame_seq = self.new_frame_seq()
10261026
if self._repeat_delay:
10271027
self.event_source.remove_callback(self._step)
@@ -1192,11 +1192,13 @@ def _init_draw(self):
11921192
# artists.
11931193
if self._init_func is None:
11941194
self._draw_frame(next(self.new_frame_seq()))
1195+
11951196
else:
11961197
self._drawn_artists = self._init_func()
11971198
if self._blit:
11981199
for a in self._drawn_artists:
11991200
a.set_animated(self._blit)
1201+
self._save_seq = []
12001202

12011203
def _draw_frame(self, framedata):
12021204
# Save the data for potential saving of movies.

‎lib/matplotlib/artist.py

Copy file name to clipboardExpand all lines: lib/matplotlib/artist.py
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,9 @@ def properties(self):
13871387
continue
13881388

13891389
try:
1390-
val = func()
1390+
with warnings.catch_warnings():
1391+
warnings.simplefilter('ignore')
1392+
val = func()
13911393
except:
13921394
continue
13931395
else:

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+8-13Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -610,16 +610,14 @@ def text(self, x, y, s, fontdict=None,
610610
else:
611611
t = mtext.Text(
612612
x=x, y=y, text=s)
613-
self._set_artist_props(t)
614613

615614
t.update(default)
616615
if fontdict is not None:
617616
t.update(fontdict)
618617
t.update(kwargs)
619-
self.texts.append(t)
620-
t._remove_method = lambda h: self.texts.remove(h)
621618

622619
t.set_clip_path(self.patch)
620+
self._add_text(t)
623621
return t
624622

625623
@docstring.dedent_interpd
@@ -676,11 +674,9 @@ def annotate(self, *args, **kwargs):
676674
"""
677675
a = mtext.Annotation(*args, **kwargs)
678676
a.set_transform(mtransforms.IdentityTransform())
679-
self._set_artist_props(a)
680677
if 'clip_on' in kwargs:
681678
a.set_clip_path(self.patch)
682-
self.texts.append(a)
683-
a._remove_method = lambda h: self.texts.remove(h)
679+
self._add_text(a)
684680
return a
685681

686682
#### Lines and spans
@@ -2895,7 +2891,7 @@ def xywhere(xs, ys, mask):
28952891

28962892
if xerr is not None:
28972893
if (iterable(xerr) and len(xerr) == 2 and
2898-
iterable(xerr[0]) and iterable(xerr[1])):
2894+
iterable(xerr[0]) and iterable(xerr[1])):
28992895
# using list comps rather than arrays to preserve units
29002896
left = [thisx - thiserr for (thisx, thiserr)
29012897
in cbook.safezip(x, xerr[0])]
@@ -2905,9 +2901,9 @@ def xywhere(xs, ys, mask):
29052901
# Check if xerr is scalar or symmetric. Asymmetric is handled
29062902
# above. This prevents Nx2 arrays from accidentally
29072903
# being accepted, when the user meant the 2xN transpose.
2908-
if not (len(xerr) == 1 or
2909-
(len(xerr) == len(x) and not (
2910-
iterable(xerr[0]) and len(xerr[0]) > 1))):
2904+
# special case for empty lists
2905+
if len(xerr) > 1 and not ((len(xerr) == len(x) and not (
2906+
iterable(xerr[0]) and len(xerr[0]) > 1))):
29112907
raise ValueError("xerr must be a scalar, the same "
29122908
"dimensions as x, or 2xN.")
29132909
# using list comps rather than arrays to preserve units
@@ -2969,9 +2965,8 @@ def xywhere(xs, ys, mask):
29692965
in cbook.safezip(y, yerr[1])]
29702966
else:
29712967
# Check for scalar or symmetric, as in xerr.
2972-
if not (len(yerr) == 1 or
2973-
(len(yerr) == len(y) and not (
2974-
iterable(yerr[0]) and len(yerr[0]) > 1))):
2968+
if len(yerr) > 1 and not ((len(yerr) == len(y) and not (
2969+
iterable(yerr[0]) and len(yerr[0]) > 1))):
29752970
raise ValueError("yerr must be a scalar, the same "
29762971
"dimensions as y, or 2xN.")
29772972
# using list comps rather than arrays to preserve units

‎lib/matplotlib/axes/_base.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_base.py
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,7 @@ def add_artist(self, a):
16761676
self._set_artist_props(a)
16771677
a.set_clip_path(self.patch)
16781678
a._remove_method = lambda h: self.artists.remove(h)
1679+
self.stale = True
16791680
return a
16801681

16811682
def add_collection(self, collection, autolim=True):
@@ -1698,6 +1699,7 @@ def add_collection(self, collection, autolim=True):
16981699
self.update_datalim(collection.get_datalim(self.transData))
16991700

17001701
collection._remove_method = lambda h: self.collections.remove(h)
1702+
self.stale = True
17011703
return collection
17021704

17031705
def add_image(self, image):
@@ -1711,6 +1713,7 @@ def add_image(self, image):
17111713
image.set_label('_image%d' % len(self.images))
17121714
self.images.append(image)
17131715
image._remove_method = lambda h: self.images.remove(h)
1716+
self.stale = True
17141717
return image
17151718

17161719
def add_line(self, line):
@@ -1729,8 +1732,19 @@ def add_line(self, line):
17291732
line.set_label('_line%d' % len(self.lines))
17301733
self.lines.append(line)
17311734
line._remove_method = lambda h: self.lines.remove(h)
1735+
self.stale = True
17321736
return line
17331737

1738+
def _add_text(self, txt):
1739+
"""
1740+
1741+
"""
1742+
self._set_artist_props(txt)
1743+
self.texts.append(txt)
1744+
txt._remove_method = lambda h: self.texts.remove(h)
1745+
self.stale = True
1746+
return txt
1747+
17341748
def _update_line_limits(self, line):
17351749
"""
17361750
Figures out the data limit of the given line, updating self.dataLim.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.