8000 Backport PR #13719: Doc: Update timeline example · matplotlib/matplotlib@4c91d7d · GitHub
[go: up one dir, main page]

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 4c91d7d

Browse files
jklymakMeeseeksDev[bot]
authored andcommitted
Backport PR #13719: Doc: Update timeline example
1 parent a3526d4 commit 4c91d7d

File tree

2 files changed

+94
-45
lines changed

2 files changed

+94
-45
lines changed

.flake8

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ per-file-ignores =
145145
examples/lines_bars_and_markers/span_regions.py: E402
146146
examples/lines_bars_and_markers/stem_plot.py: E402
147147
examples/lines_bars_and_markers/step_demo.py: E402
148+
examples/lines_bars_and_markers/timeline.py: E402
148149
examples/misc/agg_buffer.py: E402
149150
examples/misc/anchored_artists.py: E501
150151
examples/misc/contour_manual.py: E501

examples/lines_bars_and_markers/timeline.py

Lines changed: 93 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,57 +15,105 @@
1515
import matplotlib.dates as mdates
1616
from datetime import datetime
1717

18-
# A list of Matplotlib releases and their dates
19-
# Taken from https://api.github.com/repos/matplotlib/matplotlib/releases
20-
names = ['v2.2.2', 'v2.2.1', 'v2.2.0', 'v2.1.2', 'v2.1.1', 'v2.1.0', 'v2.0.2',
21-
'v2.0.1', 'v2.0.0', 'v1.5.3', 'v1.5.2', 'v1.5.1', 'v1.5.0', 'v1.4.3',
22-
'v1.4.2', 'v1.4.1', 'v1.4.0']
23-
24-
dates = ['2018-03-17T03:00:07Z', '2018-03-16T22:06:39Z',
25-
'2018-03-06T12:53:32Z', '2018-01-18T04:56:47Z',
26-
'2017-12-10T04:47:38Z', '2017-10-07T22:35:12Z',
27-
'2017-05-10T02:11:15Z', '2017-05-02T01:59:49Z',
28-
'2017-01-17T02:59:36Z', '2016-09-09T03:00:52Z',
29-
'2016-07-03T15:52:01Z', '2 8000 016-01-10T22:38:50Z',
30-
'2015-10-29T21:40:23Z', '2015-02-16T04:22:54Z',
31-
'2014-10-26T03:24:13Z', '2014-10-18T18:56:23Z',
32-
'2014-08-26T21:06:04Z']
33-
dates = [datetime.strptime(ii, "%Y-%m-%dT%H:%M:%SZ") for ii in dates]
18+
try:
19+
# Try to fetch a list of Matplotlib releases and their dates
20+
# from https://api.github.com/repos/matplotlib/matplotlib/releases
21+
import urllib.request
22+
import json
23+
24+
url = 'https://api.github.com/repos/matplotlib/matplotlib/releases'
25+
url += '?per_page=100'
26+
data = json.loads(urllib.request.urlopen(url, timeout=.4).read().decode())
27+
28+
dates = []
29+
names = []
30+
for item in data:
31+
if 'rc' not in item['tag_name'] and 'b' not in item['tag_name']:
32+
dates.append(item['published_at'].split("T")[0])
33+
names.append(item['tag_name'])
34+
# Convert date strings (e.g. 2014-10-18) to datetime
35+
dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]
36+
37+
except Exception:
38+
# In case the above fails, e.g. because of missing internet connection
39+
# use the following lists as fallback.
40+
names = ['v2.2.4', 'v3.0.3', 'v3.0.2', 'v3.0.1', 'v3.0.0', 'v2.2.3',
41+
'v2.2.2', 'v2.2.1', 'v2.2.0', 'v2.1.2', 'v2.1.1', 'v2.1.0',
42+
'v2.0.2', 'v2.0.1', 'v2.0.0', 'v1.5.3', 'v1.5.2', 'v1.5.1',
43+
'v1.5.0', 'v1.4.3', 'v1.4.2', 'v1.4.1', 'v1.4.0']
44+
45+
dates = ['2019-02-26', '2019-02-26', '2018-11-10', '2018-11-10',
46+
'2018-09-18', '2018-08-10', '2018-03-17', '2018-03-16',
47+
'2018-03-06', '2018-01-18', '2017-12-10', '2017-10-07',
48+
'2017-05-10', '2017-05-02', '2017-01-17', '2016-09-09',
49+
'2016-07-03', '2016-01-10', '2015-10-29', '2015-02-16',
50+
'2014-10-26', '2014-10-18', '2014-08-26']
51+
52+
# Convert date strings (e.g. 2014-10-18) to datetime
53+
dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]
3454

3555
##############################################################################
36-
# Next, we'll iterate through each date and plot it on a horizontal line.
37-
# We'll add some styling to the text so that overlaps aren't as strong.
56+
# Next, we'll create a `~.Axes.stem` plot with some variation in levels as to
57+
# distinguish even close-by events. In contrast to a usual stem plot, we will
58+
# shift the markers to the baseline for visual emphasis on the one-dimensional
59+
# nature of the time line.
60+
# For each event, we add a text label via `~.Axes.annotate`, which is offset
61+
# in units of points from the tip of the event line.
3862
#
3963
# Note that Matplotlib will automatically plot datetime inputs.
4064

41-
levels = np.array([-5, 5, -3, 3, -1, 1])
42-
fig, ax = plt.subplots(figsize=(8, 5))
43-
44-
# Create the base line
45-
start = min(dates)
46-
stop = max(dates)
47-
ax.plot((start, stop), (0, 0), 'k', alpha=.5)
48-
49-
# Iterate through releases annotating each one
50-
for ii, (iname, idate) in enumerate(zip(names, dates)):
51-
level = levels[ii % 6]
52-
vert = 'top' if level < 0 else 'bottom'
53-
54-
ax.scatter(idate, 0, s=100, facecolor='w', edgecolor='k', zorder=9999)
55-
# Plot a line up to the text
56-
ax.plot((idate, idate), (0, level), c='r', alpha=.7)
57-
# Give the text a faint background and align it properly
58-
ax.text(idate, level, iname,
59-
horizontalalignment='right', verticalalignment=vert, fontsize=14,
60-
backgroundcolor=(1., 1., 1., .3))
65+
66+
# Choose some nice levels
67+
levels = np.tile([-5, 5, -3, 3, -1, 1],
68+
int(np.ceil(len(dates)/6)))[:len(dates)]
69+
70+
# Create figure and plot a stem plot with the date
71+
fig, ax = plt.subplots(figsize=(8.8, 4), constrained_layout=True)
6172
ax.set(title="Matplotlib release dates")
62-
# Set the xticks formatting
63-
# format xaxis with 3 month intervals
64-
ax.get_xaxis().set_major_locator(mdates.MonthLocator(interval=3))
73+
74+
markerline, stemline, baseline = ax.stem(dates, levels,
75+
linefmt="C3-", basefmt="k-",
76+
use_line_collection=True)
77+
78+
plt.setp(markerline, mec="k", mfc="w", zorder=3)
79+
80+
# Shift the markers to the baseline by replacing the y-data by zeros.
81+
markerline.set_ydata(np.zeros(len(dates)))
82+
83+
# annotate lines
84+
vert = np.array(['top', 'bottom'])[(levels > 0).astype(int)]
85+
for d, l, r, va in zip(dates, levels, names, vert):
86+
ax.annotate(r, xy=(d, l), xytext=(-3, np.sign(l)*3),
87+
textcoords="offset points", va=va, ha="right")
88+
89+
# format xaxis with 4 month intervals
90+
ax.get_xaxis().set_major_locator(mdates.MonthLocator(interval=4))
6591
ax.get_xaxis().set_major_formatter(mdates.DateFormatter("%b %Y"))
66-
fig.autofmt_xdate()
92+
plt.setp(ax.get_xticklabels(), rotation=30, ha="right")
93+
94+
# remove y axis and spines
95+
ax.get_yaxis().set_visible(False)
96+
for spine in ["left", "top", "right"]:
97+
ax.spines[spine].set_visible(False)
6798

68-
# Remove components for a cleaner look
69-
plt.setp((ax.get_yticklabels() + ax.get_yticklines() +
70-
list(ax.spines.values())), visible=False)
99+
ax.margins(y=0.1)
71100
plt.show()
101+
102+
103+
#############################################################################
104+
#
105+
# ------------
106+
#
107+
# References
108+
# """"""""""
109+
#
110+
# The use of the following functions, methods and classes is shown
111+
# in this example:
112+
113+
import matplotlib
114+
matplotlib.axes.Axes.stem
115+
matplotlib.axes.Axes.annotate
116+
matplotlib.axis.Axis.set_major_locator
117+
matplotlib.axis.Axis.set_major_formatter
118+
matplotlib.dates.MonthLocator
119+
matplotlib.dates.DateFormatter

0 commit comments

Comments
 (0)
0