|
49 | 49 | '2014-10-26', '2014-10-18', '2014-08-26']
|
50 | 50 |
|
51 | 51 | dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates] # Convert strs to dates.
|
| 52 | +releases = [tuple(release.split('.')) for release in releases] # Split by component. |
52 | 53 | dates, releases = zip(*sorted(zip(dates, releases))) # Sort by increasing date.
|
53 | 54 |
|
54 | 55 | # %%
|
|
61 | 62 | #
|
62 | 63 | # Note that Matplotlib will automatically plot datetime inputs.
|
63 | 64 |
|
64 |
| -# Choose some nice levels: alternate minor releases between top and bottom, and |
65 |
| -# progressievly shorten the stems for bugfix releases. |
| 65 | +# Choose some nice levels: alternate meso releases between top and bottom, and |
| 66 | +# progressively shorten the stems for micro releases. |
66 | 67 | levels = []
|
67 |
| -major_minor_releases = sorted({release[:3] for release in releases}) |
| 68 | +macro_meso_releases = sorted({release[:2] for release in releases}) |
68 | 69 | for release in releases:
|
69 |
| - major_minor = release[:3] |
70 |
| - bugfix = int(release[4]) |
71 |
| - h = 1 + 0.8 * (5 - bugfix) |
72 |
| - level = h if major_minor_releases.index(major_minor) % 2 == 0 else -h |
| 70 | + macro_meso = release[:2] |
| 71 | + micro = int(release[2]) |
| 72 | + h = 1 + 0.8 * (5 - micro) |
| 73 | + level = h if macro_meso_releases.index(macro_meso) % 2 == 0 else -h |
73 | 74 | levels.append(level)
|
74 | 75 |
|
| 76 | + |
| 77 | +def is_feature(release): |
| 78 | + """Return whether a version (split into components) is a feature release.""" |
| 79 | + return release[-1] == '0' |
| 80 | + |
| 81 | + |
75 | 82 | # The figure and the axes.
|
76 | 83 | fig, ax = plt.subplots(figsize=(8.8, 4), layout="constrained")
|
77 | 84 | ax.set(title="Matplotlib release dates")
|
78 | 85 |
|
79 | 86 | # The vertical stems.
|
80 | 87 | ax.vlines(dates, 0, levels,
|
81 |
| - color=[("tab:red", 1 if release.endswith(".0") else .5) |
82 |
| - for release in releases]) |
| 88 | + color=[("tab:red", 1 if is_feature(release) else .5) for release in releases]) |
83 | 89 | # The baseline.
|
84 | 90 | ax.axhline(0, c="black")
|
85 | 91 | # The markers on the baseline.
|
86 |
| -minor_dates = [date for date, release in zip(dates, releases) if release[-1] == '0'] |
87 |
| -bugfix_dates = [date for date, release in zip(dates, releases) if release[-1] != '0'] |
88 |
| -ax.plot(bugfix_dates, np.zeros_like(bugfix_dates), "ko", mfc="white") |
89 |
| -ax.plot(minor_dates, np.zeros_like(minor_dates), "ko", mfc="tab:red") |
| 92 | +meso_dates = [date for date, release in zip(dates, releases) if is_feature(release)] |
| 93 | +micro_dates = [date for date, release in zip(dates, releases) |
| 94 | + if not is_feature(release)] |
| 95 | +ax.plot(micro_dates, np.zeros_like(micro_dates), "ko", mfc="white") |
| 96 | +ax.plot(meso_dates, np.zeros_like(meso_dates), "ko", mfc="tab:red") |
90 | 97 |
|
91 | 98 | # Annotate the lines.
|
92 | 99 | for date, level, release in zip(dates, levels, releases):
|
93 |
| - ax.annotate(release, xy=(date, level), |
| 100 | + version_str = '.'.join(release) |
| 101 | + ax.annotate(version_str, xy=(date, level), |
94 | 102 | xytext=(-3, np.sign(level)*3), textcoords="offset points",
|
95 | 103 | verticalalignment="bottom" if level > 0 else "top",
|
96 |
| - weight="bold" if release.endswith(".0") else "normal", |
| 104 | + weight="bold" if is_feature(release) else "normal", |
97 | 105 | bbox=dict(boxstyle='square', pad=0, lw=0, fc=(1, 1, 1, 0.7)))
|
98 | 106 |
|
99 |
| -ax.yaxis.set(major_locator=mdates.YearLocator(), |
| 107 | +ax.xaxis.set(major_locator=mdates.YearLocator(), |
100 | 108 | major_formatter=mdates.DateFormatter("%Y"))
|
101 | 109 |
|
102 | 110 | # Remove the y-axis and some spines.
|
|
0 commit comments